关于线程中变量值变化的问题

关于线程中变量值变化的问题

问题:如果在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();
                }
            }
        }
    }
}

这个问题需要使用线程同步机制来实现。我们可以使用互斥锁和条件变量来实现。 首先,我们定义一个全局变量来表示需要监控的变量值: ```c int monitored_value = 0; ``` 然后,我们定义一个互斥锁和一个条件变量: ```c pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond = PTHREAD_COND_INITIALIZER; ``` 接下来,我们定义两个线程,一个线程用来修改变量值,另一个线程用来监控变量值变化情况: ```c void* modify_thread(void* arg) { while(1) { // 获取互斥锁 pthread_mutex_lock(&mutex); // 修改变量值 monitored_value++; // 发送信号通知监控线程 pthread_cond_signal(&cond); // 释放互斥锁 pthread_mutex_unlock(&mutex); // 等待一段时间 sleep(1); } } void* monitor_thread(void* arg) { while(1) { // 获取互斥锁 pthread_mutex_lock(&mutex); // 等待信号 pthread_cond_wait(&cond, &mutex); // 输出变量值 printf("Monitored value changed to %d\n", monitored_value); // 释放互斥锁 pthread_mutex_unlock(&mutex); } } ``` 在主函数,我们创建两个线程并启动它们: ```c int main() { // 创建线程 pthread_t modify_tid; pthread_t monitor_tid; pthread_create(&modify_tid, NULL, modify_thread, NULL); pthread_create(&monitor_tid, NULL, monitor_thread, NULL); // 等待线程退出 pthread_join(modify_tid, NULL); pthread_join(monitor_tid, NULL); return 0; } ``` 这样,当变量值发生变化时,监控线程就会输出变量值。需要注意的是,互斥锁和条件变量的使用要遵循一定的规则,以保证线程同步的正确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值