为什么这段代码中没有发生同步?
Why isn't synchronization taking place in this code?
package atask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Q3Synchronization
{
Integer sum=new Integer(0);
Q3Synchronization(){
ExecutorService e=Executors.newFixedThreadPool(1000);
for(int i=0;i<1000;i++){
e.execute(new Sum());
}
e.shutdown();
while(!e.isTerminated()){
}
System.out.println(sum);
}
public static void main(String[]args){
new Q3Synchronization();
}
class Sum implements Runnable{
@Override
public void run() {
m();
}
public synchronized void m(){
sum=sum+1;
}
}
}
问题是:
- (同步线程)编写一个启动 1,000 个线程的程序。每个线程将 1 加到最初为 0 的变量 sum。您需要通过引用将 sum 传递给每个线程。为了通过引用传递它,定义一个整数包装器对象来保存总和。 运行同步和不同步的程序看效果
简而言之
对象方法 synchronization/locking 在每个实例的基础上工作。
说明
您正在创建 Sum
class 的 1000 个实例。对 m()
的每次调用都是同步的,但不会导致任何其他线程等待。这是因为没有对同一实例的并发调用,而是对不同实例的调用。我附上了你的代码,稍作改动:
Sum s = new Sum();
for(int i=0;i<1000;i++){
e.execute(s);
}
如果您尝试此更改,您将始终在计数器变量中得到 1000
的结果。
在构造函数中,您正在创建 new Sum()
实例并将其传递给单独的线程。 m()
方法正在获取对象上的锁(每个线程在进入同步块时都必须获取锁)。因此每个线程都可以同时执行 m()
方法,这会破坏您的多线程逻辑,因为 (sum = sum + 1)
不是原子操作。
您可以修复它:
- 将 sum 变量更改为 Atomic Integer 并使用
addAndGet()
执行加法。例如
AtomicInteger sum= new AtomicInteger(0);
和方法m
使用原子整数
public void m(){sum.addAndGet(1);}
2.Use 同一个对象获取锁,这样 m
方法就会正确同步。您可以通过在构造函数中创建一个 sum
实例变量来实现它,例如 .
final Sum sum = new Sum();
for (int i = 0; i < 1000; i++) {
`e.execute(sum);
}
package atask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Q3Synchronization
{
Integer sum=new Integer(0);
Q3Synchronization(){
ExecutorService e=Executors.newFixedThreadPool(1000);
for(int i=0;i<1000;i++){
e.execute(new Sum());
}
e.shutdown();
while(!e.isTerminated()){
}
System.out.println(sum);
}
public static void main(String[]args){
new Q3Synchronization();
}
class Sum implements Runnable{
@Override
public void run() {
m();
}
public synchronized void m(){
sum=sum+1;
}
}
}
问题是:
- (同步线程)编写一个启动 1,000 个线程的程序。每个线程将 1 加到最初为 0 的变量 sum。您需要通过引用将 sum 传递给每个线程。为了通过引用传递它,定义一个整数包装器对象来保存总和。 运行同步和不同步的程序看效果
简而言之
对象方法 synchronization/locking 在每个实例的基础上工作。
说明
您正在创建 Sum
class 的 1000 个实例。对 m()
的每次调用都是同步的,但不会导致任何其他线程等待。这是因为没有对同一实例的并发调用,而是对不同实例的调用。我附上了你的代码,稍作改动:
Sum s = new Sum();
for(int i=0;i<1000;i++){
e.execute(s);
}
如果您尝试此更改,您将始终在计数器变量中得到 1000
的结果。
在构造函数中,您正在创建 new Sum()
实例并将其传递给单独的线程。 m()
方法正在获取对象上的锁(每个线程在进入同步块时都必须获取锁)。因此每个线程都可以同时执行 m()
方法,这会破坏您的多线程逻辑,因为 (sum = sum + 1)
不是原子操作。
您可以修复它:
- 将 sum 变量更改为 Atomic Integer 并使用
addAndGet()
执行加法。例如
AtomicInteger sum= new AtomicInteger(0);
和方法m
使用原子整数
public void m(){sum.addAndGet(1);}
2.Use 同一个对象获取锁,这样 m
方法就会正确同步。您可以通过在构造函数中创建一个 sum
实例变量来实现它,例如 .
final Sum sum = new Sum();
for (int i = 0; i < 1000; i++) {
`e.execute(sum);
}