Java中易变的关键字用法

普什卡

我无法理解,如果我的变量既是volatile变量又是static变量,那么为什么线程未在输出中反映公共共享值?最后几行的输出是:线程正在运行4998Thread-0线程正在运行4999Thread-0线程正在运行4899Thread -1线程正在运行

public class Test implements Runnable{
  volatile static int  i=0;
    @Override
    public void run() {
        for(;i<5000;i++)
        {   try {
            Thread t = Thread.currentThread();
      String name = t.getName();
      //  Thread.sleep(10);
                System.out.println(i+name);
            } catch (Exception ex) {
               ex.printStackTrace();
            }
        System.out.println("Thread is running");
    }}
    public static void main(String[] args) {
    Test t=new Test();
    Thread t1=new Thread(t);
    Thread t2=new Thread(t);
    t1.start();
      // t.run();
       t2.start();
    }
    }
匿名Co夫

易失性确保变量的更改对其他线程可见。但是它不能确保同步

从您的程序的一次执行中,我得到以下输出:

Thread is running
3474Thread-1
Thread is running
3475Thread-0
Thread is running
3477Thread-0
(.... many lines where i goes from 3478 to 4998, with Thread-0 always being the one running...)
Thread is running
4999Thread-0
Thread is running
3476Thread-1
Thread is running

发生这种情况是因为线程获得了要运行的处理器时间的分片,并且它们的执行可以随时暂停和恢复。这里的线程1正在执行“ System.out.println(i + name);”行。我的值为3476。i+ name的值评估为“ 3476Thread-1”,但此时Thread-1执行停止,而Thread-0获得其时间片。线程-0一直执行到完成。然后线程1再次执行。i + name的值被评估为“ 3476Thread-1”之后以及在调用println之前,我们已将其保留调用现在已完成并打印,因此您将在结束时看到“ 3476Thread-1”。线程0将我的线程数增加到5000,但这并没有改变对i + name的求值结果,该求值结果是所有这些增长之前完成的

问题是i ++和i + name是不同的指令,线程执行可以在它们之间暂停和恢复。为了确保获得保密输出,需要确保i ++和i + name之间没有中断。也就是说,您需要使该指令集原子化。

public class Test implements Runnable{
    static Object lock = new Object();

  volatile static int  i=0;
    @Override
    public void run() {
        for(;;)
        {
            try {
                Thread t = Thread.currentThread();
                String name = t.getName();
                synchronized( lock )
                {
                    if ( i>=5000 )
                        break;
                    i++;
                    System.out.println(i+name);
                }
                //  Thread.sleep(10);
            } catch (Exception ex) {
               ex.printStackTrace();
            System.out.println("Thread is running");
            }
    }   }
    public static void main(String[] args) {
    Test t=new Test();
    Thread t1=new Thread(t);
    Thread t2=new Thread(t);
    t1.start();
      // t.run();
       t2.start();
    }
}

在该程序中,如果Thread-1在i ++和i + name之间暂停,则它将位于由synced(lock)控制的关键区域内。当线程-0开始执行时,它将到达synchronized(lock)指令,并且必须停止执行,直到线程-1恢复并退出该块为止。因为JLS确保:

同步语句(第14.19节)计算对对象的引用;然后,它尝试在该对象的监视器上执行锁定操作,并且在锁定操作成功完成之前不会进一步进行操作。执行锁定操作后,将执行synced语句的主体。如果主体的执行正常或突然完成,则会在同一监视器上自动执行解锁动作。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类常见问题

Java中default关键字的目的是什么?

来自分类Dev

Dart中的“ with”关键字

来自分类Dev

Ocaml“ in”关键字和用法

来自分类Dev

Java中的static关键字

来自分类Dev

python中关键字pass的用法

来自分类Dev

为什么“ this”关键字在Java中是final?

来自分类Dev

OCaml中的“ as”关键字

来自分类Dev

如何通过Java在IPersistentMap中查找Clojure关键字?

来自分类Dev

不同关键字(SQL)的用法

来自分类Dev

java:实例关键字的用法

来自分类Dev

您可以在JAVA中覆盖THIS关键字吗

来自分类Dev

参数c#中此关键字的用法

来自分类Dev

“ this”关键字:Java中的工作机制

来自分类Dev

欺骗Java中的private关键字

来自分类Dev

new关键字在Java中创建数组的目的

来自分类Dev

Angular Controller和controllerAs指令中的关键字用法

来自分类Dev

Java中的Monitor and Synchronized关键字

来自分类Dev

Java中的“ .class”关键字

来自分类Dev

Java中的关键字“ of”

来自分类Dev

Java中的子类和关键字this

来自分类Dev

js中的this关键字

来自分类Dev

不同关键字(SQL)的用法

来自分类Dev

Java中的Implements关键字

来自分类Dev

python中'nonlocal'关键字的用法

来自分类Dev

Java中的关键字,类似于C中的定义

来自分类Dev

javascript中const关键字的用法

来自分类Dev

了解Rust中“ super”关键字的特定用法

来自分类Dev

新关键字的本地用法

来自分类Dev

@interface 是 Java 中的关键字吗?