A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© huangqili 中级黑马   /  2014-7-12 13:36  /  1097 人查看  /  0 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

如何用sychronized来让线程同步


多线程一旦操作同一块内存的数据,就可能造成数据的混乱,也就是常说的线程安全。
Java针对这样的问题,采用sychronized关键字来帮助开发者解决这样的问题。那么sychrnized是怎么使用的呢,下面我来讲解一下。

我先给出一个出现线程安全问题的代码:
  1. Class MyThread extends Thread {
  2.     public static int index;  //静态变量index
  3.     public void run() {
  4.         for(int i = 0;i<100;i++) {
  5.         //循环打印index加1以后的值
  6.        System.out.println(getName()+":"+index++);
  7. }
  8. }
  9. }
  10. public class SyncTest {
  11.     public static void main(String[] args) {
  12.         new MyThread().start();
  13.         new MyThread().start();
  14.         new MyThread().start();
  15. }
  16. }
复制代码
以上代码中,3个线程都会去访问一个静态的变量index,由于它们获取系统时间片的时刻是不确定的,
因此它们对index的访问和修改总是穿插着的,也就会造成类似于以下的输出结果:
  1. Thread-0 : 0
  2. Thread-2 : 1
  3. Thread-0 : 2
  4. Thread-2 : 3
  5. Thread-0 : 4
  6. Thread-0 : 5
  7. Thread-1 : 6
  8. Thread-2 : 7
复制代码
通过以上的运行结果可以看出,线程之间并没有等谁执行完以后再执行,而是交织着执行的,这不符合程序的本意。
这就出现了一个好办法,就是让它们可能会出现混乱的代码同步,也就是线程之间依次排队获取资源。

在Java中,使用sychronized关键字来保证线程的同步。sychronized的工作原理是这样的:
每个对象都可以有一个线程锁,sychronized可以用任何一个对象的线程锁来锁住一段代码,
任何想进入该段代码的线程必须在解锁以后才能继续执行,否则就进入等待状态
其中,只有等占用该锁资源的线程执行完毕以后,该锁资源才会被释放。
例如,以上程序代码中的MyThread类可以这样来写,就可以很好地解决冲突的问题:
  1. class MyThread extends Thread {
  2.     public static int index;
  3.     public static Object obj = new Object();
  4.     //用任意一个对象来加锁
  5.     public void run() {
  6.        synchronized(obj) {
  7.          for(int i = 0;i<100;i++) {
  8.             System.out.println(getName()+":"+index++);
  9. }
  10. }
  11. }
  12. }
复制代码
以上代码中,把for循环的代码块加上了obj对象的锁,当一个线程进入该段代码以后,
即使其他线程进入run()方法,也需要在获得锁的情况下,才能继续运行。
另外,sysnchronized还可以加在成员方法上,这就叫做同步方法,此时的锁是加在this所引用得对象上的。
加在方法上面,还可以达到把代码段进行进一步细分的作用,也免去了需要找一个对象来加锁的步骤。

注意:不论是同步代码块,还是同步方法,它们都会损失一些效率。
因此,开发者应该根据线程可能出现问题的地方加上同步,
而不必大段大段的加上同步锁,这样可能是程序的性能降低。

总结:
sychronized关键字代表要为某一段代码加上一个同步锁,这样的锁是绑定在一个对象上边的。
如果是同步代码块,需要为该sychronized关键字提供一个对象的引用;
如果是同步方法,只需要加一个sychronized关键字的修饰。




评分

参与人数 1技术分 +2 收起 理由
Doraemon + 2

查看全部评分

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马