简体   繁体   English

Java多线程

[英]Java multi-thread

I'm a novice java programmer and kind of confused by the following code snippet. 我是Java新手,并且对以下代码段感到困惑。 Does it mean the first thread coming in will share the lock with the third one? 这是否意味着进入的第一个线程将与第三个线程共享锁? Hope someone could help me clarify. 希望有人可以帮助我澄清一下。 Thanks in advance. 提前致谢。

public class T_6 extends Thread    {
    static Object o = new Object();
    static int    counter = 0;
    int id;

    public T_6(int id)  {
        this.id = id;
    }

    public void run () {
        if ( counter++ == 1 )    //confused in here.                
            o = new Object();

        synchronized ( o ) { 
            System.err.println( id + " --->" );
            try {
                sleep(1000);
            } catch (  InterruptedException e ) {
                System.err.println("Interrupted!");
            }
            System.err.println( id + " <---" );
        }
    }

    public static void main (String args []) {
        new T_6(1).start();
        new T_6(2).start();
        new T_6(3).start();
    }
}    

When you reach the up-count and if, you do a typical check-then-act operation. 达到递增计数(如果达到)时,将执行典型的先检查后执行操作。 The problem here is that several threads can come here at the same time. 这里的问题是几个线程可以同时进入。 This will mean they will have local copies of the counter . 这意味着他们将拥有counter本地副本。 The different threads may all have a 0 local copy - meaning they will count up to 1 and create new objects - all of them. 不同的线程可能都有一个0的本地副本-这意味着它们最多可以计数1并创建新的对象-所有这些线程。 But they are stored in a static container - of which they may or may not have local copies. 但是它们存储在静态容器中,它们可能具有也可能没有本地副本。 In short, whatever happens here is accidental. 简而言之,这里发生的任何事情都是偶然的。 They may end up synchronizing over the same object - but they may try to synchronize over different objects, meaning they won't synchronize at all. 它们可能最终会在同一个对象上进行同步-但是它们可能会尝试在不同的对象上进行同步,这意味着它们根本不会同步。

You should have a look at the final and volatile keywords. 您应该看看finalvolatile关键字。

final means a reference can't be repointed once pointed somewhere. final表示引用一旦指向某处就无法重新指向。 This is a good idea for locks. 这是锁的好主意。 If you change your declaration to 如果您将声明更改为

final static Object o = new Object();

you are guaranteed that o cannot change, and all synchronizations will be over the same object. 您可以确保o不能更改,并且所有同步都将在同一对象上进行。

volatile means it is forbidden for the VM to store a thread-local copy of a variable. volatile表示VM禁止存储变量的线程本地副本。 All reads and writes must be to memory. 所有读取和写入操作必须存储到内存中。 This means that all threads will see writes that other threads do. 这意味着所有线程将看到其他线程所做的写入。

To ensure proper synchronization between multiple threads, all must acquire lock on the same object , or else synchronization will not be achieved. 为了确保多个线程之间的正确同步,所有线程都必须获取同一对象的锁 ,否则将无法实现同步。

Take a look at this part of your code: 看一下这段代码:

 if ( counter++ == 1 )    //confused in here.                
        o = new Object();

This part is not necessary at all to make the code thread-safe. 这部分对于使代码成为线程安全根本没有必要。 Remove the above code which is causing confusion. 删除上面引起混乱的代码。 You have already created instance of the object while declaring it. 声明对象时,您已经创建了该对象的实例。 Now to ensure thread-safety between all the threads, make them acquire lock on the same object which you have already created. 现在,要确保所有线程之间的线程安全,请使它们在您已创建的同一对象上获取锁。

Look here : static final Object o = new Object(); 看这里: static final Object o = new Object();

Just make the object final, to ensure you do not assign new value anywhere else in the code mistakenly/intentionally. 只是使对象成为最终对象,以确保您不会在代码中错误/有意地在其他任何地方分配新值。 You can directly use this object in synchronized fashion to ensure thread safety. 您可以以同步方式直接使用此对象,以确保线程安全。

Does it mean the first thread coming in will share the lock with the third one? 这是否意味着进入的第一个线程将与第三个线程共享锁?

Yes, moreover, due to: 是的,此外,由于:

  1. non-volatile static int counter = 0 variable 非易失性static int counter = 0变量
  2. non-atomic operation ++ 非原子操作++

each thread will have its own copy of variable counter . 每个线程将具有其自己的变量counter副本。 It means that the following condition never true : 这意味着以下条件永远不会true

if ( counter++ == 1 )    
   o = new Object();

That's why all of these threads will share the same lock on object o initialized when declaring o . 这就是为什么所有这些线程将在声明o时对初始化的对象o共享相同的锁的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM