关于java的多线程的成员变量是否线程安全的疑问?
问题描述
对于下面的程序:
public class MyThread extends Thread{ private Object obj; ......}
请问,这个MyThread里面的成员变量,是不是线程安全的?
因为,MyThread继承了Thread,其使用方式为:new MyThread().start();所以,这就意味着,每次都是new了新对象,那么,他里面的各个成员变量就是这个对象自己拥有的,所以,是安全的。我这样理解有问题吗?
问题解答
回答1:线程安全与否和是否在多个线程中使用有关
虽然你定义的是 private,但有很多种方法都可以在其它线程中间接的访问到它,所以它存在在多个线程中使用的可能,但是代码里又没有加入同步处理,所以它是不安全的。
补充使用 Thread 和 Runnable 并没有什么不同:
public class Test { public static void main(String[] args) throws Exception {MyThread mt = new MyThread();new Thread(mt).start();new Thread(mt).start();new Thread(mt).start();// MyRunable mr = new MyRunable();// new Thread(mr).start();// new Thread(mr).start();// new Thread(mr).start(); }}class MyThread extends Thread { private int ticket = 10; public void run() {for (int i = 0; i < 20; i++) { if (this.ticket > 0) {System.out.println('thread: ' + this.ticket--); }} }}class MyRunable implements Runnable { private int ticket = 10; public void run() {for (int i = 0; i < 20; i++) { if (this.ticket > 0) {System.out.println('runable: ' + this.ticket--); }} }}
一个不案例的运行示例(要多运行几次才遇得到)
thread: 10thread: 9thread: 7thread: 10thread: 6thread: 8thread: 3thread: 4thread: 5thread: 1thread: 2回答2:
每次都是new了新对象,那么,他里面的这个map就是这个对象自己拥有的,所以,是安全的。
这句话是没错的,除非你在调用子线程的这个主线程中声明了公共成员(变量)并且在子线程内部操作了这个公共变量,或者你把这个公共变量按引用传递进了子线程内部并且在子线程内部操作了它,这样才会导致线程不安全问题的出现,至于map类型本身是不是线程安全我也忘了(我记得map是一个接口,是否为线程安全要看他的具体实现把),你百度一下把。。。
如果map的实现本身是线程安全,那么无论你在多线程内部怎么操作都是没事的。(即使他在主线程中声明并且按引用传入了子线程中)
具体线程安全科普知识可以看看我以前写过的文章https://zhuanlan.zhihu.com/p/...
回答3:怎么说呢,这就好比:你把钱装在了手提箱里,一个人走在街上。你觉得这是安全的,当然了。但是一旦被抢,就不安全了。。。
线程安全说的是不同线程访问同一个数据,如果只存在一个线程,就谈不上什么线程安不安全。或者你也可以理解为是“安全”的,毕竟没有其他对象来访问,但是不是“线程安全”
回答一下问题:
这个map对象,是线程不安全的吗?
是的,线程不安全。因为虽然这里每个Thread对象都拥有唯一独立的Map对象,可是却没有“线程安全的能力”。嘛,我的理解就是这样的,好像有点啰嗦了。。。==
回答4:谢邀!在限定使用方式为new MyThread().start()的情况下是线程安全的。
回答5:虽然你声明的private但还是可以在另一个线程里读取该变量,在没有加同步锁的情况下就是线程不安全的。
题主想的这种线程安全的变量应该是在run方法里面声明的,这样的话对象就存在于线程工作内存里独享。回答6:
读没问题,写会出现线程安全问题。。。
1、用线程安全的类方法
2、用ThreadLocal
回答7:把MyThread只是看成一个类(别想它是一个线程类),把obj只是看成这个类的成员。然后就好理解了。
回答8:在多线程的情况下
public class MyThread extends Thread{ private Object obj; public void run(){if(obj==null){//A位置,这个地方是关键 obj = new Object(); system.out.println('null');} }}MyThread thread = new MyThread();//假设我的系统CPU是4核,那么实际上系统可以同时并行跑4个线程,这个时候我是同一个对象,//假设我第一个跑到A的位置,第二个也刚好跑到这个位置,//那当我第一个跑完obj是==null走到下一步的时候,obj已经重新new一个对象,//这个时候obj!=null,这可能导致的结果就是有部分无法走进A代码块里面去,//实际上在程序设计上应该需要让他走到A代码里面去的,这样就导致了线程安全的问题。thread.start();thread.start();thread.start();thread.start();回答9:
主要看你有没有访问某一个公共资源,lz这个问题,没有涉及到访问某个公共资源,所以谈不上安全不安全。
回答10:主要是看你有木有对这个变量进行操作,而且假设你每次都是new一个对象出来,就是线程安全的。
相关文章:
1. javascript - vue 数据更新了。但是dom没有更新,,,,,如图2. java基础,求解答。3. javascript - 静态页面引公共头尾文件,js怎么写吖?4. javascript - 读取页面源码,页面中所有的换行都被当成<br/>读取出来 了,,求解应该怎么让它被正确的解析5. java - 为什么要将Runnable接口的子类对象传递给Thread的构造函数?6. html5 - 百度Ueditor代码高亮和代码段滚动条冲突是怎么回事?7. javascript - 关于一段 for 循环代码执行顺序的问题8. debian - docker依赖的aufs-tools源码哪里可以找到啊?9. docker api 开发的端口怎么获取?10. css - 关于input标签disabled问题