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

java多线程总结四:volatile、synchronized示例

2011-10-28 14:20 337 查看
1、synchronized保证同步

先看一个生成偶数的类

package demo.thread;

/**
*这是一个int生成器的抽象类
*
*/
public abstract class IntGenerator {

private volatile boolean canceled = false;

public abstract int next();

public void cancel() {
canceled = true;
}

public boolean isCanceled() {
return canceled;
}
}


/*
* 产生偶数
*/
class EvenGenerator extends IntGenerator {
private int currentEvenValue = 0;
String s = "";

@Override
public int next() {
synchronized (s) {
++currentEvenValue;
++currentEvenValue;
return currentEvenValue;
}
}

//	//这样也可以
//	public synchronized int next() {
//			++currentEvenValue;
//			++currentEvenValue;
//			return currentEvenValue;
//	}
}


注意到在产生偶数是要加同步锁,否则可能线程1刚好执行了一句++currentEvenValue;操作,就被线程2抢去了cpu,此时线程2执行return currentEvenValue;这时返回的就是一个奇数。加synchronized
就是两个线程同时只能一个线程执行synchronized 块的代码。

测试代码:

package demo.thread;

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

/*
* 消费数字
*/
public class EvenChecker implements Runnable {

private IntGenerator generator;
private final int id;

public EvenChecker(IntGenerator g, int ident) {
generator = g;
id = ident;
}

public void run() {
while (!generator.isCanceled()) {
int val = generator.next();
if (val % 2 != 0) {//如果不是偶数
System.out.println(val + " not enen!");
generator.cancel();
}
}
}

public static void test(IntGenerator gp, int count) {
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < count; i++)
exec.execute(new EvenChecker(gp, i));
exec.shutdown();
}

public static void test(IntGenerator gp) {
test(gp, 10);
}

public static void main(String[] args) {
test(new EvenGenerator());
}
}


分析:如果产生偶数的类未加synchronized,那么测试程序将会出现奇数导致退出程序。

2、volatile表示原子性,可见性。

对于多个线程之间共享的变量,每个线程都有自己的一份拷贝,当线程1改变变量值时,其他线程并不马上知道该变量值改变了,volatile就保证了变量值对各个线程可见,一个线程改变该值,马上其他线程中该值也改变。原子性表明操作不可中断,如基本变量赋值。

代码示例:

package demo.thread;

public class VolatileDemo implements Runnable {

private volatile int i = 0;//volatile设置可见性

public synchronized  int getValue() {
return i;
}

private synchronized void enenIncrement() {
i++;
i++;
}

@Override
public void run() {
while (true)
enenIncrement();
}

public static void main(String[] args) {
VolatileDemo at = new VolatileDemo();
new Thread(at).start();
while (true) {
int val = at.getValue();
if (val % 2 != 0) {//出现奇数,退出程序
System.out.println(val+" is not enen!");
System.exit(0);
}
}

}
}


注意i++操作并不是原子行操作,getValue() 方法也要加synchronized 。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: