线程改变相同的变量不会同步。

7 浏览
0 Comments

线程改变相同的变量不会同步。

我的问题是代码应该将a递增1000次,然后输出它。但有时在结束时a并不是1000。\n这段代码是原始代码,显然不会起作用,因为我有多个线程访问变量a。我尝试在a++;周围放置synchronized(this),并将a标记为volatile,但仍然有时会得到错误的结果。我发现使其可靠工作的唯一方法是将join()放入for循环中,但这在使用线程的初衷上有些矛盾。\n非常感谢任何帮助。

0
0 Comments

在你发布的代码中有几个问题,所有这些问题都在对你的问题的评论中进行了报告。

我试着展示其中的主要问题:

1. 变量a是不可变的Integer类型,这意味着a++实际上是创建一个包含旧值加1的新的Integer实例。

2. 变量a被多个线程同时更新而没有进行同步,这意味着操作a=a+1可以被拆分为读取a,增加a;如果两个或多个线程同时读取a,那么增加的值将是相同的。

下面是一个修改过的版本,它使用锁来同步对资源的访问。这段代码的主要目的是显示访问a必须在线程之间同步;为了获得一个"干净的设计",你必须重新设计/更改很多其他东西。

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

public class SyncProblem {

private static int a=0;

private static class IncThread extends Thread {

private Lock lock;

public IncThread(Lock lock) {

this.lock=lock;

}

public void run() {

lock.lock();

try {

for (int i = 0; i < 100; i++) {

a++;

}

} finally {

lock.unlock();

}

}

}

public static void main(String[] args) {

Lock lock= new ReentrantLock();

IncThread[] ca = new IncThread[10];

for (int i = 0; i < 10; i++) {

ca[i] = new IncThread(lock);

ca[i].start();

}

for (IncThread c : ca) {

try {

c.join();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

System.out.println(a);

}

}

以上是对问题出现的原因和解决方法的整理。

0