金色坐标

关注互联网应用和搜索引擎技术

« Java 并发(多线程)开发技术(一)整理了一下友情链接 »

Java 并发(多线程)开发技术(二)

synchronized和volatile

一,两种线程安全问题

1,执行顺序导致的线程安全问题

当多个线程同时访问一些数据的时候,很容易导致数据的状态出现随机的不一致性,这就是典型的线程安全问题。

//假定long count是个全局变量,初始值为10

线程1 线程2
sum1 = count + 100;
count = sum1;
sum2 = count + 10;
count = sum2;

 

下面给出其中两种执行顺序(线程2的代码靠右):

第一种执行顺序 第二种执行顺序
线程1 线程2
sum1 = count + 100;  
count = sum1;   
  sum2 = count + 10;
  count = sum2; 
//现在count的结果为:120
线程1 线程2
sum1 = count + 100;  
  sum2 = count + 10;
count = sum1;  
  count = sum2;
//现在count的结果为:20


2,cpu cache导致的线程安全问题

为了高效,cpu对于全局变量的访问不一定都从内存中读取,而是为不同线程缓存一个副本在cpu的高速cache中,这样线程中访问的全局变量的值未必是最新更新的值,可能仅仅是cpu对该线程某个时刻对该变量值的缓存。

同样拿上面的例子,如果考虑cpu cache的话,即使第一种执行顺序,count的结果也同样可能是20!执行顺序和解释如下:

第一种执行顺序
线程1 线程2
sum1 = count + 100;  
count = sum1;   
  //线程2中cpu cache的count值还是10
  sum2 = count + 10;
  count = sum2; 
//现在count的结果为:20!!!!

二,synchronized基本概念

synchronized蕴含着对某个对象monitor获取的的操作,如果对应对象monitor被其他线程所拥有,则synchronized对应的代码会堵塞,直到对应对象monitor被其拥有者线程释放。

这样能保证synchronized是串行(顺序执行的),下面给出了使用synchronized解决1.2.1中出现的问题的示例:

线程1 线程2
synchronized (a) {
  sum1 = count + 100;
  count = sum1;
}
synchronized (a) {
  sum2 = count + 10;
  count = sum2;
}

*注意:synchronized 中的代码段在执行前会强制cpu重新从内存中读取全局变量的值,所以不存在上文“2,cpu cache导致的线程安全问题”中提到的问题。

三,volatile基本概念

带volatile修饰符声明的变量,在多线程并发访问的时候,会强制cpu重新从内存中读取变量的值,也避免了上文“2,cpu cache导致的线程安全问题”中提到的问题。

volatile long count = 10;

 四,简单示例

成员方法上的synchronized修饰符

public synchronized void myfun() {
//do something
}

等价于

public void myfun() {
  synchronized(this){
  //do something
  }
}

静态方法上的synchronized修饰符

public class MyClass {
public synchronized static void myStaticFun() {
//do something
}
}

等价于

public class MyClass {
public  static void myStaticFun() {
 synchronized(MyClass.class){
   //do something
 }
}
}

 




原创文章,如转载请注明:转载自金色坐标 [ http://www.kingxy.com/ ]

本文链接地址:http://www.kingxy.com/archives/189.html

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

订阅博客

  • 订阅我的博客:订阅我的博客
  • 通过Google订阅本站
  • 通过bloglines订阅本站
  • 通过抓虾订阅本站
  • 通过yahoo订阅本站

Search

Google

最新评论及回复

最近发表

金色坐标博客——京ICP备09009094号

本站采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本站内容必须也遵循“署名-非商业用途-保持一致”的创作共用协议.
KingXY Blog - This site is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License.