关于线程中变量值变化的问题
问题:如果在toy和moto中不加volatile那么匿名线程将陷入死循环阻塞生产者线程的执行。是因为匿名线程中每次获取的静态的toy和moto都是没有更新的值,因此不可能满足条件导致一直循环。
方式一:加了volatile这个修饰符后,线程就可以获取最终修改后的值了。
方式二:无意中发现一点,如果在获取的变量的值的局部范围内进行对值获取或判断,那么也是可以完成条件的。如下主方法中
volatile详细描述
public class ThreadTest {
public static void main(String[] args) {
People people = new People();
people.setName("生产者");
people.start();
int i;
for(i=0;i<100;i++){
System.out.println(i);
if(i==20){ //这样也是可以的,值也能满足条件,i在局部范围内更新了值
people.join();
}
}
//但如果用以下方式则无法执行,原因如上没有及时对i变量进行更新
if(i==20){
people.join();
}
}
}
class People extends Thread {
public volatile static int toy; //使用了volatile获取每次更新后的值
public volatile static int moto;
Thread t1;
People() {
t1 = new Thread(new Runnable() {
@Override
public void run() {
/**
* 如果不写sleep就会有问题,在people创建的线程中toy执行到20就会被这个匿名类阻塞
* 而通过jion跳到这个run方法中由于这个run方法一值在执行获取不到最新的值,那么就会一直阻塞在匿名的线程中。
*/
// try {
// sleep(5000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
while (moto < 3) {
if (toy == 20) {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
moto++;
System.out.println(Thread.currentThread().getName() + "吃了第" + moto + "个馒头");
}
}
}
});
t1.start();
t1.setName("你");
}
@Override
public void run() {
while (true) {
try {
sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
toy++;
System.out.println(getName() + "生产第" + toy + "个玩具");
if (toy == 20) {
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}