任何人都可以确认以下声明吗?
方法在方法中声明的参数和局部变量是Thread 安全;两者都是Thread的每次调用都是独占的。
另一方面,全局变量是共享的。
例如
class MyThread implements Runnable{
int _tmp = 10; //SHARED BETWEEN t1, t2, t3, and so on
public void run(){
testThreadConcurrency(arg); // arg is EXCLUSIVE FOR ALL invocation of testThreadConcurrency
}
public void testThreadConcurrency (int num){
int tmp = 10; //EXCLUSIVE FOR ALL invocation of testThreadConcurrency()
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThread _runn = new MyThread();
Thread t1 = new Thread(_runn,"t1");
Thread t2 = new Thread(_runn,"t2");
Thread t3 = new Thread(_runn,"t3");
t1.start();
t2.start();
t3.start()
}
**
请检查以下程序的输出,以证明Global 变量是SHARED
**
public class ThreadDemo {
static Object _lock = new Object();
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThread _runn = new MyThread();
Thread t1 = new Thread(_runn,"t1");
Thread t2 = new Thread(_runn,"t2");
Thread t3 = new Thread(_runn,"t3");
t1.start();
try {Thread.sleep(300);} catch (InterruptedException e1) {}
t2.start();
try {Thread.sleep(300);} catch (InterruptedException e1) {}
t3.start();
try {Thread.sleep(300);} catch (InterruptedException e1) {}
synchronized(ThreadDemo._lock){ThreadDemo._lock.notify();}
try {Thread.sleep(300);} catch (InterruptedException e1) {}
synchronized(ThreadDemo._lock){ThreadDemo._lock.notify();}
try {Thread.sleep(300);} catch (InterruptedException e1) {}
synchronized(ThreadDemo._lock){ThreadDemo._lock.notify();}
}
}
class MyThread implements Runnable{
int _tmp = 10;
public void run(){
testTestConcurrency();
}
public void testTestConcurrency(){
if(Thread.currentThread().getName().equals("t2"))
{
_tmp = 20;
}
synchronized(ThreadDemo._lock){try {ThreadDemo._lock.wait();} catch (InterruptedException e) {}}
System.out.println("_tmp = "+_tmp+"|"+Thread.currentThread().getName());
}
}
答案 0 :(得分:1)
小心!参数和变量不是对象。假设几个线程各自进入一个操作List的方法:
public Foo mumbler(List<Bar> barList) {
...
}
方法的每次调用都有自己唯一的barList 变量。任何其他线程都无法访问它,但是如果所有这些变量都持有对同一个List对象的引用,那么如果它们不相互排斥或阻止它,那么线程仍然可以(并且可能会)破坏List。通过其他方式。
编辑:
我忘记了Java传递原语作为CallByValue但是在引用的情况下使用了CallByReference ....
更好的说法是,Java按值传递对象引用:
在C ++中你可以这样写:(并不是说你想要来写它: - )
pushValueOnStack(my_type_t value, struct node &top) {
struct node new_node = malloc(sizeof(*new_node));
new_node->value = value;
new_node->next = top;
top = new_node;
}
如果您有一个局部变量 myStack ,并且您调用了pushValueOnStack(someValue, myStack),
,它实际上会更改您的局部变量以指向堆栈的新顶级节点。这是由参考号召集的。这在Java中永远不会发生。
答案 1 :(得分:0)
不完全:
T1的_tmp
未与T2的_tmp
共享,因为它们是不同的MyThread
个实例(不是类'变量,而是实例的变量)。
实际上,每次创建线程时都要重新实例化整个类:
new MyThread
如果属性实际上是类变量,则会有所不同:
static int _tmp = 10;
在这种情况下,您可能需要一些同步机制(synchronized
阻止或volatile
关键字或其他任何适应该情况的方法)
我会把它改为:
方法在方法中声明的参数和局部变量是Thread 安全;两者都是Thread的每次调用都是独占的。
但是,处理一个或多个全局变量的任何类的同一实例 在击中线程中分享那些。
最佳做法是避免线程之间的最大共享实例,以避免同步所有内容(只要性能/内存不会受到太大伤害)。
因此,您的代码段遵循最佳做法:)
-----------关于您添加的代码SNIPPET的评论-------------- :
MyThread _runn = new MyThread(); //you are using the same instance here ! delete this line
因此,在这种情况下,如果在声明每个线程时重用此实例,则该属性将为share:
Thread t1 = new Thread(_runn,"t1");
Thread t2 = new Thread(_runn,"t2");
Thread t3 = new Thread(_runn,"t3");
仅用以下方式替换:
Thread t1 = new Thread(new MyThread(), "t1"); //a new MyThread instance for each thread !
Thread t2 = new Thread(new MyThread(), "t2");
Thread t3 = new Thread(new MyThread(), "t3");
将输出(如预期:)):
_tmp = 10|t3
_tmp = 10|t1
_tmp = 20|t2
答案 2 :(得分:0)
在方法内声明的方法参数和局部变量是线程安全的;两者都是Thread的每次调用都是独占的。
方法的每次调用。没有“调用线程”这样的东西,如果存在,则没有足够的包容性。 “调用方法”包括递归的情况以及多线程的情况。
另一方面,全局变量是共享的。
是