Java中的线程同步

时间:2018-12-07 07:40:16

标签: java thread-synchronization

为什么我不能在下面的程序上实现同步:

class P
{

synchronized void pp(String s)
    {
        System.out.println (s);
    }
}

class threadA extends Thread 
{
    P ob;
    String s;
    threadA (P ob, String s)
    {
        this.ob = ob;
        this.s = s;
    }
    public void run ()
    {
        for (int i=1;i<=5;++i)
        {
        ob.pp (s);
        try
        {
            Thread.sleep (1000);
        }
        catch (Exception e) {}
        }
    }
}


class gain 
{
    public static void main(String[] args) {
        P ob = new P ();
        threadA a = new threadA (ob,"Hello User");
        threadA b = new threadA (ob,"Bye User");
        a.start();
        b.start();
    }
}

OP:

你好用户

再见用户

你好用户

再见用户

再见用户

...

我想要以下形式的OP:

您好用户

你好用户

您好用户。

再见用户

再见用户

再见用户。

还是我的同步概念不对?

4 个答案:

答案 0 :(得分:2)

您无法从P类进行此类同步。现在发生的情况是,如果当前有另一个线程 正在执行该方法,则对pp()的所有调用都将被阻止。只要方法结​​束(如果您只是要将内容打印到控制台,这将很快),则将允许下一个线程进入该方法。

除非两个线程都相互了解并相互通信,否则您无法实现的目标是不可能的。换句话说,当第一个线程完成其所需的操作时,它应明确通知第二个线程开始。这是有效地顺序执行,而不是并行执行。

更新

您想可视化正在发生的事情,所以我将在这里进行。

  1. 您创建了2个线程。
  2. 您启动第一个线程。
  3. 第一个线程开始运行,而一段时间后,第二个线程也开始运行。
  4. 当您的第一个线程运行时,它进入for循环。然后它调用P.pp()
  5. 从第一个线程调用P.pp()时,它会锁定 P对象。
  6. 由于该方法很短,因此将很快退出。
  7. 该方法退出时,它将释放P上的锁定。
  8. 如果第二个线程在第一个线程退出之前到达synchronize块,它将等待(被阻止)。
  9. 第一个线程退出时,第二个线程进入,第一个线程释放锁。
  10. 第一个线程返回循环并尝试再次调用P.pp()
  11. 这将继续,具体取决于哪个线程更快,执行的顺序会有所不同。

答案 1 :(得分:1)

Synchronized关键字意味着该代码块上的两个线程必须遵守它们尝试访问该块代码的顺序。这并不意味着执行流程已序列化。

要具有所需的内容,请尝试将 for 放在同步块中...

答案 2 :(得分:1)

您应该尝试类似的操作

class P
{

void pp(String s)
    {
        System.out.println (s);
    }
}

class threadA extends Thread 
{
    P ob;
    String s;
    threadA (P ob, String s)
    {
        this.ob = ob;
        this.s = s;
    }
    public void run ()
    {
        for (int i=1;i<=5;++i)
        {
            synchronized(ob)
            {
               ob.pp (s);
                try
                {
                    Thread.sleep (10);
                }
                catch (Exception e) {}
            }


        }
    }
}


public class gain 
{
    public static void main(String[] args) {
        P ob = new P ();
        threadA a = new threadA (ob,"Hello User");
        threadA b = new threadA (ob,"Bye User");
        a.start();
        b.start();
    }
}

e.e,即在睡眠时保持线程同步,以便您获得所需的输出,否则不确定在睡眠后哪个线程可能首先出现。参见this

答案 3 :(得分:1)

  

您能解释一下我程序的控制流程吗?

“ Hello”启动并循环运行,直到达到synchronized方法

“再见”也是如此。

“你好”是第一个获得锁的人。

“再见”阻止等待锁。

“ Hello”执行该方法并释放锁。

“再见”现在可以获取该锁,并且“你好”已将其释放

“ Bye”现在可以执行该方法,并像“ Hello”一样释放锁。

  

我该怎么办,以便在执行该方法后打招呼进入阻塞的池,并且也不会留下锁让再见来获取它

持有锁,如果要保留它,请勿释放它。

public void run() {
    synchronized(ob); { // hold the lock the whole time
        for (int i = 1; i <= 5; ++i) {
            ob.pp (s);
            try { Thread.sleep(1000); } catch (Exception e) {}
        }
    } // releases the lock here.
}