线程范围内的共享变量

举报
yd_57386892 发表于 2022/01/23 01:51:03 2022/01/23
【摘要】 1. 线程范围内的共享变量的概念           假设有2个线程,一个全局变量 int data。2个线程内的代码共用这一个变量的声明(data),但它们操作data时,data的值在这2个线程里是独立的,互不影响的。我们这里所说的互不影响,不是我们之前说的syncronized,...

1. 线程范围内的共享变量的概念

          假设有2个线程,一个全局变量 int data。2个线程内的代码共用这一个变量的声明(data),但它们操作data时,data的值在这2个线程里是独立的,互不影响的。我们这里所说的互不影响,不是我们之前说的syncronized,(线程1先修改data值,读取data值,释放锁后,线程2才可修改data和读取data,这样的话data最终的值还会变为线程2最后修改的值)。我们现在要实现的是,线程1修改了data=1, 线程2也修改了同一个data变量的值为2,data=2,最后线程1回过头再去读取时,读取出的data应该是1(它自己当时放的值就是1),线程2回头再去读取data时,读取的也是它自己的值,2.  这个data是2个线程的共享变量,但它的值在2个线程范围内各自是独立的。如下图所示:

2. 代码实现

2.1   定义全局变量

我们定义如下全局变量:

private static Map<Thread, Integer> threadData = new HashMap<Thread, Integer>();

一个map, 其中的key为正在执行的线程对象,value就是我们在上面1中所说的data变量(整数)。

   在线程1和线程2的代码中会使用到这个全局变量threadData,通过不同的key来区分线程,从而获取到对应线程中所操作的data变量。

      其本质是利用了Map(key,value)这个数据结构,实现了共享变量。那么这里的共享变量应该是Map还是Map里的value(整数)呢?从共享变量的角度来讲是这个MAP,因为我们2个线程内的代码都使用了同一个变量声明threadData,     但是从数据在线程内独立的角度来讲,我们其实是想让MAP中的value,这个核心数据的值在2个线程内是独立的。  所以,我们还是看核心数据,我认为共享变量应是Map里存储的那个value。

2.2  编写2个线程

开启2个线程,存储一个data变量的值到 MAP中的value里,到时候读取的时候,以MAP中的key来区分,读取对应线程中 曾经存储过的那个data变量的值。


  
  1. package testFuture;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import java.util.Random;
  5. public class ThreadShareData {
  6. private static Map<Thread, Integer> threadShareData = new HashMap<Thread, Integer>();
  7. public static void main(String[] args) {
  8. for(int i=0;i<2;i++){
  9. final int temp = i;
  10. new Thread(new Runnable(){
  11. @Override
  12. public void run() {
  13. int data = temp;
  14. System.out.println(Thread.currentThread().getName()
  15. + " has modify data :" + data);
  16. threadShareData.put(Thread.currentThread(), data);
  17. new DataReadA().get();
  18. }
  19. }).start();
  20. }
  21. }
  22. static class DataReadA{
  23. public void get(){
  24. int data = threadShareData.get(Thread.currentThread());
  25. System.out.println("DataReadA " + Thread.currentThread().getName()
  26. + " get data :" + data);
  27. }
  28. }
  29. }

运行日志如下:

Thread-1 has modify data :1
Thread-0 has modify data :0
DataReadA Thread-1 get data :1
DataReadA Thread-0 get data :0

      我们使用for循环创建了2个线程,每一个线程里的run函数将 for循环的索引值作为data变量的值存储在了threadShareData这个map里,同时这个map中的key为当前线程对象:Thread.currentThread()。

      这样我们在调用DataReadA对象的get函数时,获取的是每一个线程对应的value,即刚才存储的data变量值。在这里我们可以把DataReadA对象看作是一个程序模块。

那我们再创建一个模块,DataReadB,看看我们的运行结果。代码和运行日志如下,

代码:


  
  1. package testFuture;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import java.util.Random;
  5. public class ThreadShareData {
  6. private static Map<Thread, Integer> threadShareData = new HashMap<Thread, Integer>();
  7. public static void main(String[] args) {
  8. for(int i=0;i<2;i++){
  9. final int temp = i;
  10. new Thread(new Runnable(){
  11. @Override
  12. public void run() {
  13. int data = temp;
  14. System.out.println(Thread.currentThread().getName()
  15. + " has modify data :" + data);
  16. threadShareData.put(Thread.currentThread(), data);
  17. new DataReadA().get();
  18. new DataReadB().get();
  19. }
  20. }).start();
  21. }
  22. }
  23. static class DataReadA{
  24. public void get(){
  25. int data = threadShareData.get(Thread.currentThread());
  26. System.out.println("DataReadA " + Thread.currentThread().getName()
  27. + " get data :" + data);
  28. }
  29. }
  30. static class DataReadB{
  31. public void get(){
  32. int data = threadShareData.get(Thread.currentThread());
  33. System.out.println("DataReadB " + Thread.currentThread().getName()
  34. + " get data :" + data);
  35. }
  36. }
  37. }

日志:

Thread-0 has modify data :0
Thread-1 has modify data :1
DataReadA Thread-1 get data :1
DataReadA Thread-0 get data :0
DataReadB  Thread-0 get data :0
DataReadB  Thread-1 get data :1

我们发现只要是在第一个线程(Thread0)里,无论是DataReadA 还是DataReadB调用get函数,读取出来的变量值都是0,因为它当时放的就是0(日志:Thread-0 has modify data :0)。同理,

Thread-1读出来的值也是它当时存储的那个变量data,如上述日志:DataReadA Thread-1 get data :1; DataReadB  Thread-1 get data :1。

总结:

   好了,今天线程范围内共享同一个变量声明就讲到这里,记住两点就行:1. 共享同一个变量声明; 2.  两个线程内要使用的核心数据的值,是两份,修改和读取都互不干扰。

文章来源: blog.csdn.net,作者:冉航--小虾米,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/gaoxiaoweiandy/article/details/122635736

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。