我通过增加一个静态变量来实现。 100个不同的线程没有同步,但最终结果为100.我已经多次运行此代码并得到相同的结果。我的代码不需要同步吗?我使用BlueJ IDE来运行代码
public class Main {
private final static int MAX_THREADS = 100;
public static void main(String[] args) {
Thread[] threads = new Thread[MAX_THREADS];
for(int i=0; i<MAX_THREADS; i++) {
threads[i] = new Thread(new Job(), "Thread-" + i);
threads[i].start();
try{
Thread.sleep((int)(Math.random() * 1000));
}catch(InterruptedException e) {
e.printStackTrace();
}
}
for(int i=0; i<MAX_THREADS; i++) {
try {
threads[i].join();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("Final Value: %d\n", Job.getSuccessCount());
}
}
public class Job implements Runnable {
private static int successCount;
public static int getSuccessCount() {return successCount;}
@Override
public void run() {
System.out.printf("%s: Incrementing successCount %d\n", Thread.currentThread().getName(), successCount);
try{
Thread.sleep((int)(Math.random() * 10000));
}catch(InterruptedException e) {
e.printStackTrace();
}
successCount++;
System.out.printf("%s: Incrementing Complete %d\n", Thread.currentThread().getName(), successCount);
}
}
答案 0 :(得分:2)
基本上在你的代码中,由于sleep
语句(在线程和启动器中都有),你实际上开始了线程,允许大量的非繁忙时间进行更新。这就是它工作的原因。如果您的代码实际上是多线程的,那么您将面临同步问题。
答案 1 :(得分:0)
添加Wombat的答案。最终结果将始终为100,因为您在Job
课程中进行睡眠后进行一元操作。基本上,如果Java Scheduler在执行以下操作时没有更改线程的状态,则每个Job可以按顺序运行read-modify-write命令。
successCount++
但是,如果您将Job
源代码更改为read-sleep-modify-write,那么您肯定会看到过时的陈旧值。
public class Job implements Runnable {
private static int successCount;
public static int getSuccessCount() {return successCount;}
@Override
public void run() {
System.out.printf("%s: Incrementing successCount %d\n", Thread.currentThread().getName(), successCount);
int sc = successCount; // Read
try{
Thread.sleep((int)(Math.random() * 10000)); // Sleep
}catch(InterruptedException e) {
e.printStackTrace();
}
successCount = sc++; // Modify-Write
System.out.printf("%s: Incrementing Complete %d\n", Thread.currentThread().getName(), successCount);
}
}
使用这2个线程可以读取然后休眠,然后唤醒并写入相同的值到successCount
覆盖原始值。
答案 2 :(得分:0)
您的代码目前不需要同步,因为没有两个代码同时访问同一个变量。换句话说,应用程序中只有一个线程正在递增变量。
在这种情况下,这是因为递增变量所需的数量少于Math.random()* 1000。为什么会这样?让我们观察线程:
主线程:
当主线程正在执行第2步时,新线程是:
在这种情况下,一旦新线程进入休眠状态,它就会立即被杀死,因此,为了我们的目的,我们可以将其视为线程在步骤1之后立即终止,因为它会停止影响变量(它具有在步骤1)之后对变量没有影响。
为了发生同步问题,两个新线程需要一次访问该变量。为此,主线程必须在第一个新线程完成递增之前启动一个新线程。为了实现这一点,主线程必须更快:执行Math.random(),Thread.sleep()和创建新线程,所有这些都在另一个线程完成递增之前。显然不是这种情况,因此没有2个线程会立即递增,并且不会发生同步错误。
答案 3 :(得分:0)
如果你做了总和,你会发现平均有10个线程在同一时间运行,所有线程平均睡眠时间为5秒,然后进行增量。因此,平均而言,增量不会比半秒更接近,并且它们的起点也平均间隔半秒这一事实使得平均值达到整秒。这里基本上没有并发性。