精华内容
下载资源
问答
  • 通过使用volatile关键字,强制的从公共内存中读取变量的值,内存结构如图所示:使用volatile关键字增加了实例变量线程之间的可见性。但volatile关键字最致命的缺点是不支持原子性。二、volatile非原子的特性...

    一、volatile的作用

    关键字volatile是使变量在多个线程间可见,也就是强制从公共堆栈中取得变量的值,而不是从线程私有数据栈中取得变量的值。

    通过使用volatile关键字,强制的从公共内存中读取变量的值,内存结构如图所示:

    542f3de76a61942e964c47b2511153d3.png

    使用volatile关键字增加了实例变量在多个线程之间的可见性。但volatile关键字最致命的缺点是不支持原子性。

    二、volatile非原子的特性

    关键字volatile虽然增加了实例变量在多个线程之间的可见性,但它却不具备同步性,那么也就不具备原子性。

    使用volatile关键字增加了实例变量在多个线程之间的可见性。但volatile关键字最致命的缺点是不支持原子性。

    二、volatile非原子的特性

    关键字volatile虽然增加了实例变量在多个线程之间的可见性,但它却不具备同步性,那么也就不具备原子性。

    变量在内存中工作的过程如图

    13f549b8a136c7faa4fa770c7dd5dea8.png

    1、read和load阶段:从主存复制变量到当前线程工作内存;

    2、use和assign阶段:执行代码,改变共享变量值;

    3、store和write阶段:用工作内存数据刷新主存对应变量的值。

    在多线程环境中,use和assign是多次出现的,但这一操作并不是原子性,也就是在read和load之后,如果主内存count变量发生修改之后,线程工作内存中的值由于已经加载,不会产生对应的变化,也就是私有内存和公共内存中的变量不同步,所以计算出来的结果会和预期不一样,也就出现了非线程安全问题。

    对于用volatile修饰的变量,JVM虚拟机只是保证从主内存加载到线程工作内存的值是最新的,例如线程1和线程2在进行read和load的操作中,发现主内存中count的值都是5,那么都会加载这个最新的值。也就是说,volatile关键字解决的是变量读时的可见性问题,但无法保证原子性,对于多个线程访问同一个实例变量还是需要加锁同步。

    三、使用原子类进行i++操作

    除了在i++操作时使用synchronized关键字实现同步外,还可以使用AtomicInteger原子类进行实现。

    原子操作是不能分割的整体,没有其他线程能够中断或检查正在原子操作中的变量。一个原子(atomic)类型就是一个原子操作可用的类型,它可以在没有锁的情况下做到线程安全(thread-safe)。

    四、原子类也并不完全安全

    原子类在具有有逻辑性的情况下输出结果也具有随机性。要做到线程安全,还要保证调用原子类操作方法的同步

    五、下面将关键字synchronized和volatile进行一下比较:

    1、关键字volatile是线程同步的轻量级实现,所以volatile性能肯定比synchronized要好,并且volatile只能修饰于变量,而synchronized可以修饰方法,以及代码块。随着JDK新版本的发布,synchronized关键字在执行效率上得到很大提升,在开发中使用synchronized关键字的比率还是比较大的。

    2、多线程访问volatile不会发生阻塞,而synchronized会出现阻塞。

    3、volatile能保证数据的可见性,但不能保证原子性;而synchronized可以保证原子性,也可以间接保证可见性,因为它会将私有内存和公共内存中的数据做同步。

    4、再次重申一下,关键字volatile解决的是变量在多个线程之间的可见性;而synchronized关键字解决的是多个线程之间访问资源的同步性。

    5、线程安全包含原子性和可见性两个方面,Java的同步机制都是围绕这两个方面来确保线程安全的。

    六、synchronized代码块有volatile同步的功能

    关键字synchronized可以使多个线程访问同一个资源具有同步性,而且它还具有将线程工作内存中的私有变量与公共内存中的变量同步的功能。

    关键字synchronized可以保证在同一时刻,只有一个线程可以执行某一个方法或某一个代码块。它包含两个特征:互斥性和可见性。同步synchronized不仅可以解决一个线程看到对象处于不一致的状态,还可以保证进入同步方法或者同步代码块的每个线程,都看到由同一个锁保护之前所有的修改效果。

    学习多线程并发,要着重“外练互斥,内修可见”,这是掌握多线程、学习多线程并发的重要技术点。

    关注@陈大白精准面试 公众号

    展开全文
  • 如果每个线程使用的变量都是其他线程不会读取和修改,那么就不存在一致性的问题。 线程互斥接口用来保护数据,用于确保同一时间只有一个线程访问数据。 互斥:限制代码---独占 很久以前: 下面程序存在竞争问题...

    当多个控制线程共享相同的内存时呢,需要确保每个线程看到一致的数据视图。

    如果每个线程使用的变量都是其他线程不会读取和修改,那么就不存在一致性的问题。

    线程互斥接口用来保护数据,用于确保同一时间只有一个线程访问数据。

    互斥:限制代码---独占

    很久以前:

    下面程序存在竞争问题的哟,当创建20个线程,每个线程都对同一个文件进行读写操作,有可能发生N个线程同时对文件进行打开和读操作,在写的过程可能会对同一个数重复进行+1操作。比如说读到  1, 然后N个线程取到1 并对1这个数做+1操作。

    /*
        实现20个线程分别向/tmp/out写+1操作
        问题:运行结果应该为21,对于多核设备,运行会存在竞争,运行结果不确定
        (多个线程打开文件)
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <string.h>
    #define THRNUM      20  //线程数量
    #define MAXLINE     1024//从文件读最大字节数
    #define FILENAME    "/tmp/out"
    void * thr_add(void *p) 
    {
        FILE * fp; 
        char linebuf[MAXLINE];
        //open
       fp = fopen(FILENAME , "r+");
       if(fp == NULL )
       {         
            perror("fopen()");
            exit(1);
       }   
        //read
        fgets(linebuf,MAXLINE,fp);
        //write
        rewind(fp);//文件偏移量设备文件开始位置
        fprintf(fp,"%d\n",atoi(linebuf)+1);
        //close
        fclose(fp);
        pthread_exit(NULL);
    }
    
    
    int main()
    {
    
        int i , err;
        pthread_t tid[THRNUM];
        //创建线程
        for(i = 0 ; i < THRNUM ; i++)
        {   
            err = pthread_create(tid+i,NULL,thr_add,NULL);
            if(err)
            {   
                fprintf(stderr , "pthread_create():%s\n",strerror(err));
                exit(1);
            }   
        }   
        //收尸
        for(i = 0 ; i < THRNUM ; i++)
        {
            pthread_join(tid[i],NULL);
        }   
    View Code

     

    解决办法:就是互斥咯

    互斥创建

           int pthread_mutex_destroy(pthread_mutex_t *mutex);//互斥量销毁
           int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);//动态初始化:参数1:变量;参数2:属性;
           pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//静态初始化

    加锁和解锁:

           int pthread_mutex_lock(pthread_mutex_t *mutex);//阻塞
           int pthread_mutex_trylock(pthread_mutex_t *mutex);//
           int pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁

    so,程序修改为:给他加上锁

    #include <pthread.h>
    #include <string.h>
    #define THRNUM      20  //线程数量
    #define MAXLINE     1024//从文件读最大字节数
    #define FILENAME    "/tmp/out"
    
    static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;//定义个锁
    
    void * thr_add(void *p) 
    {
        FILE * fp; 
        char linebuf[MAXLINE];
        //open
       fp = fopen(FILENAME , "r+");
       if(fp == NULL )
       {         
            perror("fopen()");
            exit(1);
       }   
        pthread_mutex_lock(&mut);
        //read
        fgets(linebuf,MAXLINE,fp);
        //write
        rewind(fp);//文件偏移量设备文件开始位置
        fprintf(fp,"%d\n",atoi(linebuf)+1);
        //close
        fclose(fp);
        pthread_mutex_unlock(&mut);
        pthread_exit(NULL);
    }
    
    
    int main()
    {
    
        int i , err;
        pthread_t tid[THRNUM];
        //创建线程
        for(i = 0 ; i < THRNUM ; i++)
        {   
            err = pthread_create(tid+i,NULL,thr_add,NULL);
            if(err)
            {   
                fprintf(stderr , "pthread_create():%s\n",strerror(err));
                exit(1);
            }   
        }   
        //收尸
        for(i = 0 ; i < THRNUM ; i++)
        {   
            pthread_join(tid[i],NULL);
        }   
        pthread_mutex_destroy(&mut);// 销毁互斥
        exit(0);
    }
    View Code

    ok!

    转载于:https://www.cnblogs.com/muzihuan/p/4694923.html

    展开全文
  • 多线程是否可以同时读取同一内存变量多线程是否可以同时读取同一内存变量?只是对他进行读取不进行写入修改 那么在多线程中是否会因此而出错? itljl 2012-12-23 00:14 读可以,修改不可以。 ...

    当两个或多个线程同时对一块内存区域进行“只读”时,不会有问题,但如果发生“写”时,就会有问题,需要加锁。也就是多个线程访问某个数据没有问题,但如果访问同时可能修改该数据的话,就要加锁。


    多线程是否可以同时读取同一内存变量?

    多线程是否可以同时读取同一内存变量?只是对他进行读取不进行写入修改 那么在多线程中是否会因此而出错?

    itljl 2012-12-23 00:14
    读可以,修改不可以。

    华玉欣 2012-12-23 02:40
    可以,可以,可以,可以,可以,可以,可以,可以,可以,可以,可以,可以,可以,

    ttyige 2012-12-24 19:18
       貌似我就经常 出错。。

    0xff 2012-12-24 19:58
      

    xyxyyy23 2012-12-24 20:50
    看看...............

    yfz0574 2012-12-24 22:35
    刚确认过了,在多核多线程下,也不可能因为读内存而产生线程出错问题.

    qq617119142 2012-12-24 22:37
        

    风精灵 2012-12-24 23:07
    看变量的类型,固定长度的就没问题(如:整数、日期等),非固定的不论读、写,都是要进行保护的(如:文本、字节集、各种数组等)

    hpjyb 2012-12-25 01:02
    顶下。。。

    yfz0574 2012-12-25 08:06
    引用
    引用第8楼风精灵于2012-12-24 23:07发表的  :
    看变量的类型,固定长度的就没问题(如:整数、日期等),非固定的不论读、写,都是要进行保护的(如:文本、字节集、各种数组等)  img: http://bbs.eyuyan.com/images/back.gif

    8楼这个说法可有依据?多线程事关重大,你说的不会是易语言的多线程BUG吧,这个跟楼主的问题无关,请看修正版.并不是多线程本身的问题,而是易语言的BUG.

    cx421774557 2013-01-24 09:37
    可以,可以,

    100501882 2013-01-24 11:20
    引用
    引用第8楼风精灵于2012-12-24 23:07发表的  :
    看变量的类型,固定长度的就没问题(如:整数、日期等),非固定的不论读、写,都是要进行保护的(如:文本、字节集、各种数组等)  img: images/back.gif


    实际上,文本,字节集,只读不写都是固定的长度,长度值永远不会变,只读不写不会冲突的。还有数组,只要数组成员是固定,且所有成员都只读。完成1点问题都没有。

    以上说的您没必要相信,自己花2分钟写点代码分别多线程测试就知道。
    展开全文
  • 处理器可以使用高速缓存加速对内存的访问(或者编译器可以将值存储到寄存器中以便进行更... 这表示在这样的系统上,对于同一变量,在两个不同处理器上执行的两个线程可能会看到两个不同的值! 解决这个问题的其中一个

          处理器可以使用高速缓存加速对内存的访问(或者编译器可以将值存储到寄存器中以便进行更快的访问)。在一些多处理器体系结构上,假如在一个处理器的高速缓存中修改了内存位置,没有必要让其它处理器看到这一修改,直到刷新了写入器的高速缓存并且使读取器的高速缓存无效。
      
      这表示在这样的系统上,对于同一变量,在两个不同处理器上执行的两个线程可能会看到两个不同的值!

          解决这个问题的其中一个方法是用volatile。

          当一个变量被声明成 volatile,任何对该变量的写操作都会绕过高速缓存,直接写入主内存,而任何对该变量的读取也都绕过高速缓存,直接取自主内存。这表示所有线程在任何时候看到的 volatile 变量值都相同。

     

    展开全文
  • linux多线程变量自增问题分析

    千次阅读 2020-07-26 14:50:50
    如果两个线程试图几乎在同一时间对同一变量做增量操作而不进行同步的话,结果可能就不一致了,在上述代码中,我们传进线程函数的是变量的地址,那么变量i自增后,可能还没有写回内存单元,就被另一个线程读取了。...
  • 然后有个总的方法getAllData来New 线程线程调用getData方法,通过一些全局变量来控制获取的是数据A B或C 因为线程调用方法是无参数的。如果获取数据是同一个来源的最好lock一下,保证同一时间内只有一个线程进入...
  • 线程-线程同步

    2017-06-18 19:10:46
    我们知道线程共享同一进程内的资源。如果每个线程使用的变量,其他线程都不会读取个修改,那么就不存在一致性问题。...两个或线程同时修改同一变量时,也需要同步。跟前面信号讲的问题相同,考虑增量操作情况。增量
  • 互斥量线程的优势主要是能通过全局变量来共享信息,但在多线程程序中,必须要确保多个线程不会同时修改同一变量(临界资源),或者某一线程不会读取正由其他线程修改的变量。当程序以非原子方式访问共享资源有一定...
  • VC多线程临界区

    2019-10-04 01:49:29
    在使用多线程时,一般非常少有多个线程全然独立的工作。往往是多个线程同一时候操作一个全局变量来获取程序的执行结果。多个线程同一时候訪问同一个全局变量,假设都是读取操作,则不会出现故障。假设是写操作,则会...
  • 本实验主要考察多线程对单例模式的操作,和多线程同一资源的读取,两个知识。实验涉及到三个类: 1)一个pojo类Student,包括set/get方法。 2)一个线程类,设置student的成员变量age和name的值为111和111 3)另...
  • 多线程自增问题

    千次阅读 2017-04-05 17:24:14
    如果两个线程试图几乎在同一时间对同一变量做增量操作而不进行同步的话,结果可能就不一致了,在上述代码中,我们传进线程函数的是变量的地址,那么变量i自增后,可能还没有写回内存单元,就被另一个线程读取了,那...
  • 线程试图在同一时间修改同一变量时,因为修改通常不是一步到位的: 从内存中读入寄存器 在寄存器中修改变量 将新值写回内存 这个时候可能出现数据不一致,导致程序错误 线程安全:指的是线程在执行
  • 线程同步与线程安全

    2017-10-25 22:33:45
    个线程共享同一内存的时候,可能会出现某个线程在修改变量,而另一线程读取到不一致的数据。所以不得不使用锁,在同一时间只允许一个线程访问该变量。 如图描述这种同步,如果线程B要读取该变量,首先要获得锁...
  • 线程不安全的原因

    2020-06-14 10:52:39
    3.2如果是线程尝试读取同一变量 线程安全 3.3如果是线程修改不同变量 线程安全 **4.**内存可见性导致线程安全问题 **5.**指令重排序(Java的编译器在编译代码时,会针对指令进行优化,调整指令的先后顺序,提高...
  • 1、使用多线程可以有效利用CPU资源,线程享有相同的地址空间和内存,这些线程如果同时读写变量,导致互相干扰,就会产生并发问题,为了避免并发问题,绝不能让多个线程读取或写入相同的变量,因此python中使用了全局...
  • 多线程小结

    2020-04-21 01:03:14
    线程共享实例变量(成员变量),会引发线程安全问题。 在使用synchronize或者reentrantLock时,读取值和修改值应该在同一代码块中; 某些情况下,可使用volatile修饰变量强制更新内存和私有线程中的变量,使得...
  • 多线程

    2017-04-14 17:43:42
    多线程设计模式: 1.Single Threaded Execution Pattern  [同一时刻只允许一个线程操作]    比喻:三个挑水的和尚,只能同一时间一个人过桥,不然都掉河里喂鱼了。  总结:在多个线程同时要访问的方法上加上...
  • 多线程(三)volatile

    2020-03-25 10:51:38
    2. volatile的作用是确保所有线程同一-时刻读取到的共享变量的值是一致的。 3.如果某个线程对volatile修饰的共享变量进行更新,那么其他线程可以立刻看到这个更新。 硬件系统架构演进 计算机在运行程序时,每条...
  • 在本文开始介绍多线程中的设计模式 1.Single Threaded Execution Pattern 同一时刻只允许一个线程操作 ...总结在多线程要访问的方法上加上synchronized关键字 ...总结 将多线程共享的变量用finnal 修饰
  • //多线程读取文件,同时把读取到的文件内容再用多线程写入到指定的空白文件中,实现多线程读写文件//从程序中可以看到使用WaitForSingleObject()函数。来控制多线程访问同一文件时不至于发生冲突。通过CEvent g_...
  • Posix条件变量

    2014-03-31 22:20:23
    当一个线程修改了某个变量,而另一个线程试图读取它时,或者两个线程同时修改同一变量,就会影响到数据的完整性,为防止这个问题,操作系统提供了一种相互排斥对象,简写为mutex。在多线程程序中,mutex是通过编程来...
  • 线程同步

    2009-04-26 23:36:00
    1. 线程同步当一个线程修改变量时...所以,当两个线程线程试图对在同一时间修改或读取同一变量时,就需要同步。例如增量操作,它可以分成三步:1) 从内存单元读入寄存器2) 在寄存器中进行变量值的增加3) 把新的值
  • 线程共享相同的内存时,需要每一个线程看到相同的试图,当一个线程修改变量时,其他线程也可以读取或修改这个变量,就需要线程的同步,确保他们不会访问到无效的变量。 互斥量: 在变量修改时间多于以一个...
  • 当一个线程修改变量时,而其他线程也可以读取或者修改这个变量,就需要对这些线程同步,确保他们不会访问到无效的变量。   为了让线程访问数据不产生冲突,这要就需要对变量加锁,使得同一时刻只有一个线程可以...
  • ThreadLocal介绍ThreadLocal可以创建只能由同一线程读取和写入的变量。因此,即使两个线程正在执行相同的代码,并且代码具有对 ThreadLocal变量的引用,那么这两个线程不能看到对方的ThreadLocal变量。实际上...
  • 实际上,这些问题只有在一或多个线程向这些资源做了写操作时才有可能发生,只要资源没有发生变化,多个线程读取相同的资源就是安全的。多线程同时执行下面的代码可能会出错:public class Counter { pro
  • 多线程_CAS原理分析

    2020-08-21 15:18:29
    我们知道多线程操作共享资源时,会出现三个问题:可见性、有序性以及原子性。...而且如果操作的共享变量是基本数据类型,并且同一时间只对变量进行读取或者写入的操作,那么原子性问题也得到了解决,就不会

空空如也

空空如也

1 2 3 4 5 ... 11
收藏数 208
精华内容 83
热门标签
关键字:

多线程读取同一变量