【问题标题】:is it possible to change the value of a instance variable from the different class thread After acquiring a lock获取锁后是否可以从不同的类线程更改实例变量的值
【发布时间】:2016-07-21 11:43:50
【问题描述】:

是否可以在获取锁后从不同的类线程中更改实例变量的值。

我有一个类 ThreadTest,它有字符串测试实例变量。 在 Run 方法中,我锁定了 String 测试实例变量。

如果 JVM 已经对实例变量进行了锁定,那么为什么我能够从主线程更改它的值。

ThreadTest.class

包 com;

公共类 ThreadTest 实现 Runnable{

String test;
int i=100;

public ThreadTest(String test) {
    super();
    this.test = test;
}


@Override
public void run() {
    // TODO Auto-generated method stub


//  Thread.currentThread().dumpStack();
    while(i>0)
    {   
        synchronized(test){


        System.out.println("Thrad Test Run---  "+test+" - "+i+"- -- "+Thread.currentThread().getName());

            try {
                Thread.sleep(1000);

            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        i--;
    }
}

}

Test.class

包 com;

公共类测试{

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub


    ThreadTest testThread=new ThreadTest("1");
    Thread thread=new Thread(testThread);
    thread.setName("First Thread");
    Thread thread1=new Thread(testThread);
    thread1.setName("Second Thread");

    thread.start();
    thread1.start();
    int i=100;  
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    while(true)
    {
        //here im accessing the 'test' that is instance variable of ThreadTest.
        // and First Thread alredy acquired a lock on 'test'.
        //so according to the JAVA threading testThread.test=10 is not valid.
        //how multiple threads are able to change the value of testThread.test
        testThread.test="10";
        //System.out.println("main thread...");
    }



}

}

【问题讨论】:

    标签: java multithreading synchronization


    【解决方案1】:

    似乎对同步语句的作用感到困惑。

    1. 同步不锁定实例变量,它“锁定”一个对象。 (实际上,这里没有使用“锁定”这个词。它获取对象的“监视器”。)当使用同步语句时(如上),评估提供的表达式以确定要获取哪个对象的监视器。例如,以下是有效的,虽然可能是无意义的同步语句:

      synchronized ("1") {
         // ... 
      }
      
      synchronized (new Object()) {
         // ...
      }
      

      第一个获取表示字符串文字“1”的字符串对象的监视器。第二个获取一个全新对象上的监视器(这对于管理并发性从不有用)。

    2. 同步用于标记程序中的关键部分。临界区是不能同时执行的代码块。 See Critical Section on Wikipedia

      关于上面的代码,同步不会阻止实例(或类)变量的读取或写入。

    以下内容可能会有所帮助:Synchronization from the Java Tutorial

    【讨论】:

      【解决方案2】:

      获取锁后是否可以...

      如果线程 A 获得了锁,这不会限制线程 A 以任何方式做任何事情的能力。

      如果线程 A 获得了一个锁,它限制了线程 B 做一件事的能力:它阻止线程 B 获得相同的锁,直到线程 A 释放它。它不会阻止线程 B 做任何其他事情。特别是它不会阻止线程 B 访问或修改“锁定”的对象。

      是否可以改变实例变量的值...

      是的,如果变量不是final

      ...来自不同的班级

      A 类中的方法是否可以直接引用 B 类中声明的变量取决于访问级别privateprotectedpublic默认值)在变量的声明中指定。 https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

      synchronized 块的使用和线程的使用不会以任何方式改变访问级别的含义。

      当然,A 类中的方法也可以通过调用 B 类的某些方法来间接影响 B 类中的 private 变量。

      ...来自不同的...线程

      如果 A 类中的方法可以直接或间接影响 B 类中声明的变量,那么执行该方法的线程无关紧要。所有线程都看到同一个堆。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-09
        • 1970-01-01
        • 2012-01-19
        • 2016-05-21
        相关资源
        最近更新 更多