java - Thread.sleep 也阻塞其他线程,在其他方法上工作,以及在同步方法内部调用自身

标签 java multithreading synchronized

class Common
{

public synchronized void synchronizedMethod1() 
    {
        System.out.println("synchronized Method1 called");
        try
        {
        Thread.sleep(1000);
        } 
        catch (InterruptedException e) 
        {
        e.printStackTrace();
        }
        System.out.println("synchronized Method1 done");
    }

public synchronized void synchronizedMethod2() 
{
    System.out.println("synchronized Method2 called");
    try
    {
    Thread.sleep(1000);
    }
    catch (InterruptedException e) 
    {
    e.printStackTrace();
    }
    System.out.println("synchronized Method2 done");
}
}

在上面的类中,我有两个同步方法,我从另一个类的 run 方法调用它们。其他类代码如下:

public class ThreadClass implements Runnable
{
    private int id = 0;
    private Common common;

public ThreadClass(int no, Common object)
{
    common = object;
    id = no;
}

public void run()
{
    System.out.println("Running Thread " + Thread.currentThread().getName());
    try 
    {
        if (id == 11) 
        {
            common.synchronizedMethod1();
        } 
        else
        {
            common.synchronizedMethod2();
        }
    } 
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

public static void main(String[] args)
{
    Common c = new Common();
    ThreadClass tc = new ThreadClass(11, c);
    ThreadClass tc1 = new ThreadClass(20, c);
    Thread t1 = new Thread(tc, "Thread 1");
    Thread t2 = new Thread(tc1, "Thread 2");
    t1.start();
    t2.start();
}
}

从主方法中,我启动了两个不同的线程。在 run 方法中,我给出了一个条件,将两个不同的线程发送到不同的同步方法。代码产生的输出是:

Running Thread Thread 2
Running Thread Thread 1
synchronized Method2 called
synchronized Method2 done
synchronized Method1 called
synchronized Method1 done

我对输出的问题是: 当线程 2 进入同步方法 2 时,它会打印第 3 行输出并进入 hibernate 状态 1 秒。现在,由于线程 1 没有被任何东西阻塞,所以它应该在第三行输出之后执行并打印输出的第五行,然后应该进入休眠状态,但是当线程 2 进入休眠状态时,这种情况不会发生,它使线程 1 也 sleep ,然后第一个线程 2 完成其执行,之后线程 1 完成其执行。

如果我从方法中删除同步关键字,则不会发生这种行为。 您能否解释一下使用和不使用同步关键字处理代码的不同方式背后的原因。

提前致谢。

最佳答案

Such a behavior is not happening if I remove synchronized keyword from methods. Can you please explain me the reason behind different way of processing the code with and without synchronized keywords.

这实际上是 synchronized 关键字的全部目的。当同一个类有多个同步实例方法时,一次只能执行一个。你已经写了这个:

class Common {
    public synchronized void synchronizedMethod1(){}
    public synchronized void synchronizedMethod2(){}
}

由于两种方法都是同步的,因此一次只能执行一种方法。其中一个无法启动,另一个已完成。

这是如何工作的?简而言之,您有一个 Common 对象并调用它的同步实例方法。当您调用 synchronzedMethod1 时,该方法将“锁定”Common 对象(称为“获取锁”)。虽然该方法对该 Common 对象具有锁定,但如果您尝试在同一对象上调用任何其他同步方法,它会尝试锁定它,并且会发现它已经被锁定。因此,任何其他锁定该对象的尝试都将挂起,直到他们可以这样做为止。一旦 synchronizedMethod1 完成,它将解锁 Common 对象(称为“释放锁”),然后任何人都可以尝试锁定它,例如 synchronizedMethod2

简而言之,synchronized 特意做到了这一点,因此同一类的两个同步方法不能同时发生。这很有用,因为不这样做可能会导致一些有问题的行为。例如,ArrayList 不会执行此操作,因此,如果一个线程尝试将对象添加到 ArrayList,而另一个线程尝试迭代它,则可能会抛出 ConcurrentModificationException 并使每个人都感到难过。

关于java - Thread.sleep 也阻塞其他线程,在其他方法上工作,以及在同步方法内部调用自身,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42746069/

相关文章:

android - 我可以在 View 之间共享 Paint 实例吗?

java - 使用相同的变量打印收据,因此每个项目都会传递相同的值。

java - 从 SOAP 附件中提取的 ZIP 文件损坏

c# - System.Threading.Thread 在 .NET Core 中的含义与在 .NET Framework 中的含义相同吗?

java - Java SE 的 ManagedExecutorService、ManagedTask 和 ManagedTaskListener 替代方案

java - 使用 System.out.println(Thread.currentThread().getName() + ""+count);导致同步

java - Date() 显示有关参数不匹配的错误

java - 如何在页面对象模型类-Java中使用鼠标悬停 Action ?

c - GNU Pth(Gnu 可移植线程)的 Windows 端口/实现

java - 两类同步