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

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

2011-11-01 09:56 477 查看
1、synchronized保证同步

先看一个生成偶数的类

view
plain

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;

}

}

</span>

view
plain

<span style="font-size:16px;">/*

* 产生偶数

*/

class EvenGenerator extends IntGenerator {

private int currentEvenValue = 0;

String s = "";

@Override

public int next() {

synchronized </span>(s) {

++currentEvenValue;

++currentEvenValue;

return currentEvenValue;

}

}

// //这样也可以

//
synchronized </span>int next() {

// ++currentEvenValue;

// ++currentEvenValue;

// return currentEvenValue;

// }

}</span>

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

测试代码:

view
plain

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());

}

}</span>

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

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

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

代码示例:

view
plain

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);

}

}

}

}

</span>

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