我阅读了以下程序并在博客中回答。
int x = 0;
boolean bExit = false;
线程1(未同步)
x = 1;
bExit = true;
线程2(未同步)
if (bExit == true)
System.out.println("x=" + x);
线程2是否可以打印“x=0
”?
Ans :是(原因:每个帖子都有自己的变量副本。)
你是如何解决的? Ans :通过使用make两个线程在公共互斥锁上同步或使两个变量都变为volatile。
我怀疑是:如果我们将2变量设为volatile,那么2个线程将共享主内存中的变量。这是有道理的,但是在同步的情况下如何解决它,因为线程都有自己的变量副本。
请帮帮我。
答案 0 :(得分:0)
取决于实现方式,该实现方式决定线程是否将变量的副本保留在自己的内存中。如果是类级变量,则线程具有共享访问权限;如果是局部变量,则线程将保留它的副本。我将提供两个示例来说明这一事实,请看一下。
在您的示例中,如果我理解正确,则您的代码应如下所示-
package com.practice.multithreading;
public class LocalStaticVariableInThread {
static int x=0;
static boolean bExit = false;
public static void main(String[] args) {
Thread t1=new Thread(run1);
Thread t2=new Thread(run2);
t1.start();
t2.start();
}
static Runnable run1=()->{
x = 1;
bExit = true;
};
static Runnable run2=()->{
if (bExit == true)
System.out.println("x=" + x);
};
}
输出
x=1
我总是得到该输出。这是因为线程共享该变量,并且当一个线程更改该变量时,其他线程可以看到它。但是在现实生活中,我们永远无法说出哪个线程将首先开始,因为在这里线程没有做任何事情,因此我们无法看到预期的结果。
现在以这个例子-
在这里,如果您将for循环中的i
变量作为静态变量,则线程将不会保留其副本,也不会看到所需的输出,即,即使u,计数值也不会每次为2000已同步计数增量。
package com.practice.multithreading;
public class RaceCondition2Fixed {
private int count;
int i;
/*making it synchronized forces the thread to acquire an intrinsic lock on the method, and another thread
cannot access it until this lock is released after the method is completed. */
public synchronized void increment() {
count++;
}
public static void main(String[] args) {
RaceCondition2Fixed rc= new RaceCondition2Fixed();
rc.doWork();
}
private void doWork() {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for ( i = 0; i < 1000; i++) {
increment();
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for ( i = 0; i < 1000; i++) {
increment();
}
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
/*if we don t use join then count will be 0. Because when we call t1.start() and t2.start()
the threads will start updating count in the spearate threads, meanwhile the main thread will
print the value as 0. So. we need to wait for the threads to complete. */
System.out.println(Thread.currentThread().getName()+" Count is : "+count);
}
}