Java Synchronized用法1
2013-09-28 23:09
323 查看
1.背景
Java中需要资源共享,如对象中的一些数据,而数据是私有的,往往通过创建方法去访问这些数据,当多个线程去访问这些数据(调用方法)时,往往会产生冲突,Synchronized可以有效的防止冲突(Thinking in java14.2.2)。
2.原理
使用Synchronized去修饰方法时,调用此方法的对象将会被“上锁”,此时锁住的是对象,不是代码块或者此方法。
eg.
一个对象包含两个synchronized方法funcA() and funB(),线程1去访问A,对象此时被上锁,线程2、3....无法访问funcA() and funcB().
也就是说一个含有Synchronized方法的对象,在任何时间,只允许一个线程访问此对象的Synchronized方法。
3.实例
1000个线程同时对一个对象中的数据进行增减操作。没有使用synchronized之前,输出结果不确定,也就是同一时刻出现至少两个线程访问数据;使用Synchronized之后,输出确定。
4.疑问
当只使用inc方法时,数据时一致的,为何?
解答:若将inc函数中休眠与count自加调换位置,如下,就会发现结果不一致。在上诉例子中因为当线程1访问inc方法时,首先就是执行count自加,此时其他线程获取的是自加之后的count值,不存在冲突。而交换之后,线程1访问inc方法,首先sleep 100ms, 这段时间就可能会被其余的线程抢占而去执行count自加,当返回线程1时,而count值仍然是未加之前的,导致数据异常。
Java中需要资源共享,如对象中的一些数据,而数据是私有的,往往通过创建方法去访问这些数据,当多个线程去访问这些数据(调用方法)时,往往会产生冲突,Synchronized可以有效的防止冲突(Thinking in java14.2.2)。
2.原理
使用Synchronized去修饰方法时,调用此方法的对象将会被“上锁”,此时锁住的是对象,不是代码块或者此方法。
eg.
一个对象包含两个synchronized方法funcA() and funB(),线程1去访问A,对象此时被上锁,线程2、3....无法访问funcA() and funcB().
也就是说一个含有Synchronized方法的对象,在任何时间,只允许一个线程访问此对象的Synchronized方法。
3.实例
1000个线程同时对一个对象中的数据进行增减操作。没有使用synchronized之前,输出结果不确定,也就是同一时刻出现至少两个线程访问数据;使用Synchronized之后,输出确定。
public class SyncTest{ int count = 0; static int number = 1000; public SyncTest(){ } public void inc(){ this.count +=1000; try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void dec(){ this.count -= 1000; try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args){ final SyncTest st = new SyncTest(); Thread[] threadArray = new Thread[number]; for(int i=0;i<number;i++){ threadArray[i] = new demoThread(String.valueOf(i),st); } for(int i=0;i<number;i++){ threadArray[i].start(); } for(int i=0;i<number;i++){ try { threadArray[i].join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(String.valueOf(st.count)); } } class demoThread extends Thread{ String name; SyncTest st; public demoThread(String name,SyncTest st){ this.name = name; this.st = st; } @Override public void run() { // TODO Auto-generated method stub st.inc(); st.dec(); System.out.println("Thread"+name+" start run"); } }
4.疑问
当只使用inc方法时,数据时一致的,为何?
解答:若将inc函数中休眠与count自加调换位置,如下,就会发现结果不一致。在上诉例子中因为当线程1访问inc方法时,首先就是执行count自加,此时其他线程获取的是自加之后的count值,不存在冲突。而交换之后,线程1访问inc方法,首先sleep 100ms, 这段时间就可能会被其余的线程抢占而去执行count自加,当返回线程1时,而count值仍然是未加之前的,导致数据异常。
public void inc(){ try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } count += 100; }
相关文章推荐
- Java中synchronized用法
- Java中Synchronized的用法
- Java synchronized用法
- Java中Synchronized的用法
- Java中Synchronized的用法
- MongoDB自增序列实现 - Java多线程同步 synchronized 用法
- java中synchronized的用法详解
- java中synchronized用法
- Java多线程,线程同步synchronized,线程死锁【线程池常规用法】多线程并发处理
- java中synchronized关键字的用法
- java中synchronized的用法(1)
- java中synchronized用法
- java中synchronized的用法详解
- Java synchronized关键字用法
- java中synchronized的用法详解
- Java中Synchronized的用法
- java中synchronized用法
- Java中Synchronized的用法
- Java中Synchronized的用法
- Java中Synchronized的用法