0 0

一个多线程共享变量的问题,请教下大家15

工作中遇到了这么一个问题,想请教下大家。伪码如下:

public class AAAAA{

    public boolean enable = true; // [b]非violate[/b]

    // 线程A执行
    public void methodA{
        while(enable){
            .........
        }
        system.out.println("----------------------");
    }

    // 线程B执行
    public void methodB{
        enable = false;
    }
}


前提:线程A和线程B一定都会执行code。
问题:线程A是否有可能会永远退不出循环?如果存在这种可能,请详细说明下原因,谢谢。

本人认为不会存在这种情况,但是有同事说存在这种可能,原因是JVM指令重排序优化。我查了些资料,没有找到充足的证据来证明此事,所以想在这里请教下各位大侠,先行谢过了。

问题补充:去掉活性失败的例子,如果MethodA的实现变更为
public void methodA{
    while(true){
       dosomething();
       if (enable){
          dosomething();
       }
       dosomething();
    }
}

那么enable也会永远为true吗?
2012年7月30日 00:13

15个答案 按时间排序 按投票排序

0 0

采纳的答案

看看effective java 中文版第二版 230页  如果没错的话 这个描述叫做火星失败 liveness failure 是因为 while(enable) 被jvm 优化成 if(!enable) {
while (true)
}  所以需要设置同步访问 或者是 在enable 前 加上 violate 这样 当enable变化时 这样他能保证任何一个线程在读取该域的时候能看见最新被修改的值

以上全是引用书中的话 若有不全的地方 请看书籍

2012年7月30日 12:18
0 0

当有多个线程同时来存取某一个对象时,就出现可见性问题.
为了保证变量的可见性,一般可以用锁、 synchronized关键字、 volatile关键字或直接设置为final ;

线程在MethodA 方法中,只是一次从寄存器读取进来,一直没有改变变量enable的值,一般不会主动更新主存的值到工作内存中,所以很有可能一直下去.

2012年7月31日 15:49
0 0

昨天可能没有理解你的意思。后来想了想,这里跟JVM指令重排没有关系的,如果有A线程和B线程同时操作AAAA,但是至于A会不会退出循环,跟A线程和B线程执行的具体情况而定,假如线程B已经执行完了methodB,而且修改的enable对线程A可见,那么A就退出循环了。
  加上volatile主要是保证修改值后对另外的线程可见。这样可以保证线程间的同步,但是并不意味着不加volatile就不能实现同步,只是发生的事件是一个概率事件。也就是说线程A同样可以拿到线程B已经修改的enable的值。

    最后的结论是:这里讨论线程A是否有可能会永远退不出循环意义不大。因为这个事件本身是不确定事件。只有线程B执行完methodB后且修改enable值对线程A可见,而线程A执行methodA,这样就退出循环。是一个概率事件。如果非要对你那个下结论的话我觉得"不可能",既然是概率事件当样本足够多的话总会发生的。

    希望我的回答能帮到你

2012年7月31日 08:03
0 0

public boolean enable = true你需要加上volatile修饰符,确保内存可见性

2012年7月30日 17:53
0 0

自己写个程序run一下,不就知道结果了么

2012年7月30日 16:51
0 0

跟“指令重排序优化”无关,两个线程读取的enable可能是不同的,为了优化执行变量可能在cpu缓存里有副本,cpu缓存也是多级的,再加上内存里的副本,不一定读到的是哪个

可以给 enable加 volatile修饰 一种弱强制同步

2012年7月30日 15:53
0 0

if (enable){
          dosomething();
       }

如果你这个dosomething显示执行methodB,然后将enable = true;
这样就可以实现线程A一直循环下去了

2012年7月30日 15:53
0 0

如果你的2个线程是共享一个AAAAA对象的话,那是必定会退出循环的,2个线程共享的是相同的对象,同一个内存地址,线程B如果改变了enable的地址值,那么线程A的调用的methodAwhile循环条件就变成了false,那就退出了循环。

2012年7月30日 14:52
0 0

建议你把java编程思想第21章看几遍 边看边实践 看到你懂为止 比任何回答都强

2012年7月30日 12:54
0 0

可能的,原因是enable不是同步即时的(即你说的非violate的),然后线程A就会看不到enable的变化,就一直不断的执行while代码

2012年7月30日 11:44
0 0

程序的本意是希望methodB中断methodA,但是,由于编译器判断在methodA里面没有修改过enable ,因此可能只执行一次对enable 到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面的“enable 副本”,导致循环永远无法退出,如果将enable加上volatile修饰,则编译器保证对此变量的读写操作作都不会被优化(肯定执行),那么当methodB执行完后,methodA即可退出循环。

2012年7月30日 11:31
0 0

首先,你确定你同一个AAAAA的对象被A,B线程同时操作了,才会出现线程问题。
假如是的话,除非B线程没有执行到,那么可能会一直执行下去,基本上不太可能,线程B总会改变这个enable。

  但是假如说:methodA和methodB都加上同步锁,出现的可能性就极大了。

2012年7月30日 11:12
0 0

不会出现线程问题  enable是这个成员变量

2012年7月30日 10:18
0 0

多线程 静态字段,都可以修改

2012年7月30日 08:58
0 0

根据你的伪代码不会出现线程问题吧,你的enable是一个私有变量。
我不知道是不是没有理解你的意思。

2012年7月30日 08:37

相关推荐

    Qt 多线程访问同一个变量

    标题"Qt 多线程访问同一个变量"涉及到的是如何在多线程环境下确保对共享资源(此处为一个全局变量)的安全访问。描述中提到了使用互斥锁来解决这个问题,并通过创建两个线程ThreadA和ThreadB来演示这一过程。 首先...

    C#多线程互斥实例 多线程获取同一变量

    在这个"多线程互斥实例 多线程获取同一变量"的示例中,我们将探讨如何在多个线程中安全地访问共享资源,避免数据不一致性和竞态条件。 首先,我们需要理解多线程中的一些核心概念: 1. **线程**:线程是操作系统...

    java多线程_java多线程下变量共享_

    在多线程环境中,变量共享是一个常见的需求,但也是引发问题的关键点。本篇文章将深入探讨Java多线程下变量共享的问题以及解决策略。 在Java中,线程共享变量可以通过两种方式实现:静态成员变量和实例成员变量。...

    创建线程,利用互斥实现线程共享变量通信

    一、题目: 创建线程,利用互斥实现线程共享变量通信 二、目的 掌握线程创建和终止,加深对线程和进程概念的理解,会用同步与互斥方法实现线程之间的通信。 三、内容和要求 软件界面上点“创建线程” 按钮,创建三个...

    多线程线程变量赋值

    总的来说,“多线程线程变量赋值”是一个关于如何在多线程环境中管理线程私有数据的问题。通过`ThreadLocal`,我们可以创建和操作线程特有的变量,避免了数据同步的复杂性,但在使用过程中需要注意内存管理和线程...

    C语言多线程中变量累加问题的分析

    变量累加问题是指多个线程同时访问和修改同一个变量时,导致变量的值不确定的问题。在上面的代码中,我们定义了一个全局变量`g_iTestInteger`,并且在多个线程中对其进行累加操作。 由于多个线程同时访问和修改`g_...

    JAVA多线程并发操作全局变量

    NULL 博文链接:https://toknowme.iteye.com/blog/2212529

    qt线程共享数据 信号和槽方式

    即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的。 Qt 线程间共享数据是本文介绍的内容,多的不说,先来啃内容。Qt线程间共享数据主要有两种方式...

    采用全局变量方式实现多线程的通信

    在多线程编程中,线程间的通信是一个关键的议题,尤其当多个线程需要共享数据或协调工作时。全局变量作为一种简单的方式被用于实现线程间的通信,尤其是在MFC(Microsoft Foundation Classes)框架下。下面我们将...

    多线程同时操作全局变量的出错演示

    然而,多线程编程也带来了一些挑战,尤其是当多个线程同时访问共享资源,如全局变量时,可能会出现竞态条件(Race Condition)和其他并发问题。本文将深入探讨标题“多线程同时操作全局变量的出错演示”所涉及的知识...

    CVI 线程锁、线程安全变量实例

    在实际应用中,你可能会遇到这样的场景:多个线程需要共享一个资源,例如,更新一个全局计数器或者访问一个数据库连接。这时,线程锁和线程安全变量就派上用场了。首先,创建一个线程锁,然后在每个需要访问共享资源...

    Linux下C语言多线程编程实例

    接着,我们定义了两个线程函数 `thread1` 和 `thread2`,这两个函数都将对共享变量 `number` 进行递加操作。在每个线程函数中,我们首先输出当前线程的信息,然后使用互斥锁 `pthread_mutex_lock` 和 `pthread_mutex...

    Python写的多线程共享全局变量(带中文注释)

    Python写的多线程共享全局变量代码,用于学习多线程开发,可以直接运行,并且带中文注释,方便初学者学习使用。

    使用三种VC的多线程同步方法编写一个多线程的程序

    1.使用三种VC的多线程同步方法编写一个多线程的程序(要求在屏幕上先显示Hello,再显示World)。 1)基于全局变量的多线程同步程序; 2)基于事件的多线程同步程序; 3)基于临界区的多线程同步程序。

    多线程不同步读写共享资源代码

    多线程不同步读写共享资源 文章配套代码 我在很早的时候就听说多线程不同步是可以...写线程判断条件 if(下一个指针==读线程指针) 其实这就是一简单的生产者与消费者问题。 以下是实现方法 共享资源 我使用循环缓冲区

    java 多线程 加减变量

    java 多线程 加减变量

    多线程资源共享集合

    多线程是指在一个进程中同时执行多个线程,每个线程都有自己的程序计数器、系统栈和局部变量。在多核或多处理器系统中,多线程可以充分利用硬件资源,提高程序的执行效率。然而,当多个线程访问和修改同一资源时,...

    c++通过结构体(struct)全局变量在多线程中传递参数

    在C++编程中,多线程环境下的通信和数据共享是一项关键任务。本文将深入探讨如何使用结构体(struct)和全局变量在多线程间传递参数,特别是在Linux环境下使用`make`进行编译的情况。 首先,理解全局变量。全局变量...

    CVI 04.多线程数据保护(安全变量

    多线程数据保护(安全变量)"这个主题主要关注如何在并发执行的线程间安全地共享数据,避免数据竞争、死锁等并发问题。在本文中,我们将深入探讨多线程环境中的数据保护策略,特别是安全变量的概念及其应用。 首先,...

Global site tag (gtag.js) - Google Analytics