多线程处理之lock语句

简介:     lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。 案例1、 class ThreadingExample {     class ...

    lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。

案例1、


  1. class ThreadingExample
  2. {
  3.     class C1
  4.     {
  5.         private bool deadlocked = true;
  6.         private object locker = new object();
  7.         public void LockMe(object o)
  8.         {
  9.             //lock (this)
  10.             lock(locker)
  11.             {
  12.                 while (deadlocked)
  13.                 {
  14.                     deadlocked = (bool)o;
  15.                     Console.WriteLine("I am locked:(");
  16.                     Thread.Sleep(500);
  17.                 }
  18.             }
  19.         }
  20.         public void DoNotLockMe()
  21.         {
  22.             Console.WriteLine("I am not locked:");
  23.         }
  24.     };
  25.     static void Main()
  26.     {
  27.         C1 c1 = new C1();
  28.         Thread t1 = new Thread(c1.LockMe);
  29.         t1.Start(true);
  30.         Thread.Sleep(100);
  31.         //lock (c1)
  32.         //{
  33.             c1.DoNotLockMe();
  34.             c1.LockMe(false);
  35.        // }
  36.         Console.ReadLine();
  37.     }
  38. }


 

image

关键点:

1. lock(this)的缺点就是在一个线程(例如本例的t1)通过执行该类的某个使用"lock(this)"的方法(例如本例的LockMe())锁定某对象之后, 导致整个对象无法被其他线程(例如本例的主线程)访问 - 因为程序员可以在任何其他线程(例如本例的主线程)访问该类的时候使用类似lock(c1)的代码,因此我们在设计类的时候就最好未雨绸缪,而不是把负担留给用户。

2. 我们应该使用不影响其他操作和不会被外部对象锁定的的私有成员作为locker。

3. 在使用lock的时候,被lock的对象(locker)一定要是引用类型的,如果是值类型,将导致每次lock的时候都会将该对象装箱为一个新的引用对象(事实上如果使用值类型,C#编译器(3.5.30729.1)在编译时就会给出一个错误)。

 

MSDN上的案例


  1. namespace ThreadLock
  2. {
  3.     class Account
  4.     {
  5.         private Object thisLock = new Object();
  6.         int balance;
  7.         Random r = new Random();
  8.         public Account(int initial)
  9.         {
  10.             balance = initial;
  11.         }
  12.         int Withdraw(int amount)
  13.         {
  14.             // This condition will never be true unless the lock statement
  15.             // is commented out:
  16.             if (balance 0)
  17.             {
  18.                 throw new Exception("Negative Balance");
  19.             }
  20.             // Comment out the next line to see the effect of leaving out
  21.             // the lock keyword:
  22.             lock (thisLock)
  23.             {
  24.                 if (balance >= amount)
  25.                 {
  26.                     Console.WriteLine("Balance before Withdrawal : " + balance);
  27.                     Console.WriteLine("Amount to Withdraw : -" + amount);
  28.                     balance = balance - amount;
  29.                     Console.WriteLine("Balance after Withdrawal : " + balance);
  30.                     return amount;
  31.                 }
  32.                 else
  33.                 {
  34.                     return 0; // transaction rejected
  35.                 }
  36.             }
  37.         }
  38.         public void DoTransactions()
  39.         {
  40.             for (int i = 0; i 100; i++)
  41.             {
  42.                 Withdraw(r.Next(1, 100));
  43.             }
  44.         }
  45.     }
  46.     class Test
  47.     {
  48.         static void Main()
  49.         {
  50.             Thread[] threads = new Thread[10];
  51.             Account acc = new Account(1000);
  52.             for (int i = 0; i 10; i++)
  53.             {
  54.                 Thread t = new Thread(new ThreadStart(acc.DoTransactions));
  55.                 threads[i] = t;
  56.             }
  57.             for (int i = 0; i 10; i++)
  58.             {
  59.                 threads[i].Start();
  60.             }
  61.             Console.ReadLine();
  62.         }
  63.     }
  64. }


image

多个线程共同访问Account acc对象,使用lock(object)很好的处理这访问冲突的问题。

相关文章
|
Java 开发者 C++
Java多线程同步大揭秘:synchronized与Lock的终极对决!
Java多线程同步大揭秘:synchronized与Lock的终极对决!
199 5
|
Java 开发者 C++
Java多线程同步大揭秘:synchronized与Lock的终极对决!
【6月更文挑战第20天】在Java多线程编程中,`synchronized`和`Lock`是两种关键的同步机制。`synchronized`作为内置关键字提供基础同步,简单但可能不够灵活;而`Lock`接口自Java 5引入,提供更复杂的控制和优化性能的选项。在低竞争场景下,`synchronized`性能可能更好,但在高并发或需要精细控制时,`Lock`(如`ReentrantLock`)更具优势。选择哪种取决于具体需求和场景,理解两者机制至关重要。
213 1
|
分布式计算 并行计算 安全
在Python Web开发中,Python的全局解释器锁(Global Interpreter Lock,简称GIL)是一个核心概念,它直接影响了Python程序在多线程环境下的执行效率和性能表现
【6月更文挑战第30天】Python的GIL是CPython中的全局锁,限制了多线程并行执行,尤其是在多核CPU上。GIL确保同一时间仅有一个线程执行Python字节码,导致CPU密集型任务时多线程无法充分利用多核,反而可能因上下文切换降低性能。然而,I/O密集型任务仍能受益于线程交替执行。为利用多核,开发者常选择多进程、异步IO或使用不受GIL限制的Python实现。在Web开发中,理解GIL对于优化并发性能至关重要。
202 0
|
Java 测试技术
Java多线程同步实战:从synchronized到Lock的进化之路!
【6月更文挑战第20天】Java多线程同步始于`synchronized`关键字,保证单线程访问共享资源,但为应对复杂场景,`Lock`接口(如`ReentrantLock`)提供了更细粒度控制,包括可重入、公平性及中断等待。通过实战比较两者在高并发下的性能,了解其应用场景。不断学习如`Semaphore`等工具并实践,能提升多线程编程能力。从同步起点到专家之路,每次实战都是进步的阶梯。
165 0
|
11月前
|
Java 开发者
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
122 4
|
12月前
|
Java 开发者
在 Java 多线程编程中,Lock 接口正逐渐取代传统的 `synchronized` 关键字,成为高手们的首选
【10月更文挑战第6天】在 Java 多线程编程中,Lock 接口正逐渐取代传统的 `synchronized` 关键字,成为高手们的首选。相比 `synchronized`,Lock 提供了更灵活强大的线程同步机制,包括可中断等待、超时等待、重入锁及读写锁等高级特性,极大提升了多线程应用的性能和可靠性。通过示例对比,可以看出 Lock 接口通过 `lock()` 和 `unlock()` 明确管理锁的获取和释放,避免死锁风险,并支持公平锁选择和条件变量,使其在高并发场景下更具优势。掌握 Lock 接口将助力开发者构建更高效、可靠的多线程应用。
81 2
|
Java
领略Lock接口的风采,通过实战演练,让你迅速掌握这门高深武艺,成为Java多线程领域的武林盟主
领略Lock接口的风采,通过实战演练,让你迅速掌握这门高深武艺,成为Java多线程领域的武林盟主
88 7
|
算法 Java
JUC(1)线程和进程、并发和并行、线程的状态、lock锁、生产者和消费者问题
该博客文章综合介绍了Java并发编程的基础知识,包括线程与进程的区别、并发与并行的概念、线程的生命周期状态、`sleep`与`wait`方法的差异、`Lock`接口及其实现类与`synchronized`关键字的对比,以及生产者和消费者问题的解决方案和使用`Condition`对象替代`synchronized`关键字的方法。
JUC(1)线程和进程、并发和并行、线程的状态、lock锁、生产者和消费者问题
|
安全 Java 开发者
Java多线程同步:synchronized与Lock的“爱恨情仇”!
Java多线程同步:synchronized与Lock的“爱恨情仇”!
146 5
|
Java 开发者
揭秘!为什么大神都爱用Lock接口处理线程同步?
揭秘!为什么大神都爱用Lock接口处理线程同步?
129 5