`

线程同步与通信

 
阅读更多

线程同步(互斥)

同步的需求是指同一段代码,一个线程在执行的时候,不能有别的线程也在执行。

为此,Java提供了锁的机制:

synchronized(lock){
  // some code need synchronized
}
一个线程在执行到同步代码块的时候,就需要先拿到lock对象作为锁,能拿到的前提是lock对象身上的锁还没有被别的线程拿走,否则就要等待了。执行完毕同步代码块之后,线程就会把lock对象的锁归还,别的线程才能获取到锁并继续往下执行。

怎样才能真正锁住是认真考虑的事情,锁对象的选择至关重要。这里要记住的一点是,字符串作为锁的时候一定要小心:

String key1 = "a";
String key2 = "a";


这个时候,key1和key2可以看成是同一个对象,用key1做为锁的线程和用key2作为锁的线程能够实现同步互斥。但是

String key1 = new String("a");
String key2 = new String("a");
或者
String key1 = p1 + p2;
String key2 = p1 + p2;
两种情况的key1和key2就不能作为锁了,因为他们是不同的对象。

代码块级别的锁使用的是显式的锁,就是明确指定了锁是哪个。成员方法级别的同步使用的是隐式的锁---this;同理,静态方法使用的锁则为该方法所在类的类对象(class)。



线程通信

线程通信指的是线程间的协调执行。

同步互斥的代码最好不要放到匿名的Thread内部类中,而应该归纳到一个外部类里面。
通过查询运行条件,判断是否该继续执行还是应该等待,继续等待就调用锁对象的wait方法。如果条件满足,自己执行完之后,如果条件满足,需要改变条件变量,并调用notify来唤醒其他等待的线程。
如此循环...

总的来说,线程通信依赖的是synchronized机制和条件变量。CPU不知道谁该执行谁该等待,它只会随机调一个线程来跑,线程只能依靠自身的检测来确定自己应该执行还是应该等待其他线程执行完毕满足条件之后再执行。这就是线程通信。



分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics