Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/rest/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是否与嵌套类同步,但与全局变量同步?(爪哇)_Java_Synchronization_Nested_Nested Class_Locks - Fatal编程技术网

Java 是否与嵌套类同步,但与全局变量同步?(爪哇)

Java 是否与嵌套类同步,但与全局变量同步?(爪哇),java,synchronization,nested,nested-class,locks,Java,Synchronization,Nested,Nested Class,Locks,我正试图找出用这种代码修复这种中断的并发性问题的最佳方法。我尝试过在“index++”周围添加一个锁,但是有没有更好的方法来实现并发性呢 public class MainClass { public static short index = 0; public static void main(String[] args) { MainClass testConc = new MainClass(); T

我正试图找出用这种代码修复这种中断的并发性问题的最佳方法。我尝试过在“index++”周围添加一个锁,但是有没有更好的方法来实现并发性呢

    public class MainClass {
        public static short index = 0;

        public static void main(String[] args) {
            MainClass testConc = new MainClass();
            Thread thr1 = new Thread(testConc.new MyRunnable());
            thr1.start();
            Thread thr2 = new Thread(testConc.new MyRunnable());
            thr2.start();
        }    

        class MyRunnable implements Runnable {
            private static final Object lock = new Object();
            public void run() { 
                while (index < 99) {
                    System.out.println(index);
                    synchronized(lock) {
                        index++;
                    }
                }
            }
        }
    }
public类MainClass{
公共静态短索引=0;
公共静态void main(字符串[]args){
MainClass testConc=新的MainClass();
Thread thr1=新线程(testConc.new MyRunnable());
thr1.start();
Thread thr2=新线程(testConc.new MyRunnable());
thr2.start();
}    
类MyRunnable实现Runnable{
私有静态最终对象锁=新对象();
public void run(){
而(指数<99){
系统输出打印项次(索引);
已同步(锁定){
索引++;
}
}
}
}
}

AtomicInteger比在索引周围锁定要好++ 它是专门为这个用例设计的

另外,通过锁定,您并没有实现并发性,而是实现了线程安全性/原子性(如果实现正确)


顺便说一下,我在代码中没有看到“中断的并发性问题”

您的锁应该与用于保护的数据处于同一级别(
MainClass
)。类变量
index
实际上应该具有
private
作用域,因为同步只在类中发生

此外,正如Tomáš在注释中指出的,变量应该标记为
volatile
,这保证了对its值的任何更改对所有线程都是可见的(自Java 5以来)。这样就不需要同步对
索引的读取访问。因此,更正后的代码如下所示:

public class MainClass {
  private static volatile short index = 0;
  private static final Object lock = new Object();
  ...
如果希望程序按顺序将索引从
0
输出到
98
,并且每个索引值只输出一次,则需要将
run()
方法修改为:

public void run() {
    while (index < 99) {
        synchronized (lock) {                    
            // double-check for threads that made it here
            // before #index got incremented to 99 by the thread that
            // made the final increment
            if (index < 99) {
                System.out.println(index);
                index++;
            }
        }
    }
}
public void run(){
而(指数<99){
已同步(锁定){
//仔细检查这里的线程
//在#index被
//做最后的增量
如果(指数<99){
系统输出打印项次(索引);
索引++;
}
}
}
}

请注意,需要使用for
索引<99
,因为在
while
条件下对值求值后,
索引可能已被另一个线程更改。如果使用旧版本的
run()

增加
MainClass
生成的线程数,您将看到这一点?您希望输出什么?您得到什么?@jas它是一个静态字段,因此是一个共享字段lock@jas,锁对象是静态的,这意味着它在所有实例之间共享。@MickMnemonic我试图运行它。它有时会以“97、98、5”等输出结束。@TomášZíma这可能是因为它在锁外打印?我无法将索引从短改为其他任何内容。所以记住这一点,还有其他的解决办法吗。如果没有“同步(锁定)”,则会导致并发性中断。如果我使“run()”同步,它会工作吗?不,它不会与synchronized run()一起工作。它将在每个线程上独立地“synchronized”run()。就性能而言,使用ReentrantLock优于synchronized(obj)。我确信你可以把索引变为别的东西,因为你已经用线程来处理它了,要考虑它(你可以写一个提供值的吸气剂)。类变量
index
也应该声明为
volatile
,让JVM知道它的值可以被不同的线程操作。@TomášZíma,但是可以声明一个短的
volatile
?@thestranger是的,可以。谢谢@TomášZíma,我编辑了关于
volatile
用法的帖子。