您的位置:首页 > 编程语言 > Java开发

实例分析java中synchronized关键字用法

2017-02-14 16:32 1011 查看
在多线程运行下,对共享资源的访问要遵循互斥原则,否则会出现资源访问的错误。这时可以使用synchronized关键字对互斥的资源或是方法、对象进行加锁,实例如下:

首先在MyDataGenerator类中有一个偶数数据,以及一个布尔标志数据,代码如下:

public class MyDataGenerator {
private int evenData;
private boolean cancel;

MyDataGenerator() {
this.evenData = 0;
this.cancel = false;
}

public int nextEven() {
evenData ++;      // 出错的位置
evenData ++;
return evenData;
}

public boolean getCancel() {
return cancel;
}

public int getEvenData() {
return evenData;
}

public void cancel() {
cancel = true;
System.out.println("Now the data is: " + evenData);
}
}


默认evenData是每次调用nextEven()方法后值加2,这样就一直使evenData为偶数。然后接下来创建一个用于测试的类MyDataChecker:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MyDataChecker implements Runnable {
private MyDataGenerator myDataGenerator;
private int checkerId;

MyDataChecker(MyDataGenerator dg, int id) {
myDataGenerator = dg;
checkerId = id;
}

public void run() {
while (!myDataGenerator.getCancel()) {
if (myDataGenerator.nextEven() % 2 != 0) {
myDataGenerator.cancel();
System.out.println("Not even number, failure.");
}
}
}

public static void testDataFailure(MyDataGenerator myDataGenerator, int threadNum) {
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < threadNum; i++)
exec.execute(new MyDataChecker(myDataGenerator, i));
exec.shutdown();
}

}


在此类中启用多个MyDataChecker线程来执行DataGenerator中的nextEven()方法,在MyDataGenerator加入执行:

public static void main(String[] args) {
MyDataChecker.testDataFailure(new MyDataGenerator(), 10);
}


启用10个DataChecker线程,共同访问同一个Generator,此时因为nextEven()不是互斥访问,会存在一定的几率在两次evenData+1之间进程进行调度切换,从而evenData变成奇数。从而出现错误:

Now the data is: 1074
Not even number, failure.


这时在nextEven()方法前加入synchronized关键字可以使进程互斥访问此方法,在使用时加锁,从而不再出错:

public synchronized int nextEven() {
evenData ++;
evenData ++;
return evenData;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: