为什么使用了volatile关键字,两个线程还是没有同步成功!求救
public class TestVolatile implements Runnable {
private volatile int i = 0; @Override
public void run() {
while (i < 10) {
if ("bbb".equals(Thread.currentThread().getName()) && i == 3) {
i = 11;
}
System.out.println("hello world! " + i + " time(s)");
i++; try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public static void main(String[] args) {
Thread t1 = new Thread(new TestVolatile());
Thread t2 = new Thread(new TestVolatile());
t1.setName("aaa");
t2.setName("bbb");
t1.start();
t2.start();
}
}
public class TestVolatile implements Runnable {
private volatile int i = 0; @Override
public void run() {
while (i < 10) {
if ("bbb".equals(Thread.currentThread().getName()) && i == 3) {
i = 11;
}
System.out.println("hello world! " + i + " time(s)");
i++; try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public static void main(String[] args) {
Thread t1 = new Thread(new TestVolatile());
Thread t2 = new Thread(new TestVolatile());
t1.setName("aaa");
t2.setName("bbb");
t1.start();
t2.start();
}
}
解决方案 »
- 【分享】基于SWING+JAVAFX的JAVA MP3播放器
- 关于JAVA核心技术卷II中一个例子的问题,大家一起看下
- 关于JAVA编译的疑难问题
- 初学者编写的链表程序编译通过了,运行时老报错误(望达人求助一下,谢了)
- 寻找java相关的开源书籍或网址
- 急需JAVA人才,有意请于我联系!
- (Eclipse版没人气,俺就在这问了)俺用Eclpise30,编译不了原来的tomcat项目,用2.0没这个问题!咋回事啊?
- 请哪位大侠解释一下,什么是PreparedStatement语句池,如何实现。rowset中的PreparedStatement也有此特性吗?谢谢
- 如何将tomcat 添加到win2000 的服务中。
- 关于Tomcat的配置问题,请熟悉Tomcat的人指教
- runtime调用sqlplus跑脚本不能正常退出,但是直接拿语句到cmd跑却正常
- 菜鸟求助 股票交易 买卖部分设计
但是在i递增10次这段时间内,难道都没有一次去同步吗?
如果没有一次去同步,那么volatile这个关键字到底是约束什么的。
保證變量的賦值過程是原子性,但不是保證線程同步
volatile保证的赋值过程是原子性的
因为JAVA不能像C一样,确保赋值过程是原子的,所以要加volatile
我给出另一种解决方法,可以把i作为临界区,凡是用到i的地方都要互斥使用,这样就能实现同步了public class TestVolatile implements Runnable
{
private static int i = 0;
private static Object obj = new Object(); public void run()
{
int tmp;
synchronized(obj)
{
tmp = i;
i++;
}
while (tmp < 10)
{
if ("bbb".equals(Thread.currentThread().getName()) && tmp == 3)
{
synchronized(obj)
{
i = 11;
tmp = i;
}
}
System.out.println("hello world! " + tmp + " time(s) " + Thread.currentThread().getName());
synchronized(obj)
{
tmp = i;
i++;
} try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
} public static void main(String[] args)
{
Thread t1 = new Thread(new TestVolatile());
Thread t2 = new Thread(new TestVolatile());
t1.setName("aaa");
t2.setName("bbb");
t1.start();
t2.start();
}
}
如果想让多线程同步要用synchronized关键字才行。
ibm的developerworks网站有几篇关于volitile的文章去看看就明白了。
Thread t1 = new Thread(new TestVolatile());
Thread t2 = new Thread(new TestVolatile());
t1.setName("aaa");
t2.setName("bbb");
t1.start();
t2.start();
}楼主注意这段程序, 这是在每一个线程中都分别创建了一个对象, 两个线程访问的是两个不同的对象,并且变量又不是静态的, 何来同步的问题。
我最近也在研究这个关键字的使用,貌似没有办法测试它。如果不加volatile这个关键字的话只是说可能会发生问题,但是在java里面几率很小很小, 我试过很多种情况都测不出来, 所以我认为在java里面应该是可以忽略了。我问过做C++的同事,他们说这种情况在c++里面比较常见, java里面就可以不计了。
Thread t1 = new Thread(new TestVolatile());
Thread t2 = new Thread(new TestVolatile());应该改为
TestVolatile t= new TestVolatile()
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
这样用同一个TestVolatile 对象去创建两个线程才能同步
volatile是线程属性共享,而不是对象属性共享