繁体   English   中英

线程:同步块

[英]thread: Synchronized Block

我对同步块有疑问。 执行以下代码后,输出为:

Inside run=>thread 2
Inside run=>thread 1
Inside run=>thread 1
Inside run=>thread 2
Inside run=>thread 2
Inside run=>thread 1
Inside run=>thread 2
Inside run=>thread 1
Inside run=>thread 1
Inside run=>thread 2

我期望输出,因为只有一个线程会首先执行同步块,然后只有第二个线程才能访问synchornized块。 可能是我了解错误的概念?

 package com.blt;

    public class ThreadExample implements Runnable {
        public static void main(String args[])
        {


            System.out.println("A");
            Thread T=new Thread(new ThreadExample());
            Thread T1=new Thread(new ThreadExample());
            System.out.println("B");
            T.setName("thread 1");
            T1.setName("thread 2");
            System.out.println("C");
            T.start();
            System.out.println("D");
            T1.start();
        }


     synchronized public void run()
    {
        for(int i=0; i<5; i++)
        {
            try
            {
             System.out.println("Inside run=>"+Thread.currentThread().getName());
             Thread.currentThread().sleep(2000);
            }
             catch(InterruptedException e)
            {
                e.printStackTrace();
            }
          }  
    }
    }

您的每个线程都在不同的对象上同步。 所以是的,他们不会互相锁定。 但更重要的是, run方法是为Runnable接口定义的, 没有同步修饰符,因此您不应在其中添加一个(如您已经看到的那样,它没有您预期的效果)。

要记住的关键是,当您在方法上使用synced修饰符时:

public synchronized void someMethod();

实际上,它与使用synchronized(this) 在这两种情况下,您都锁定在对象监视器上。 如果有多个对象,则有多个监视器。

这是您自己的示例的修改版本,它将按您的预期工作。 它使用一个通用的对象监视器(在本例中为您的类本身),以便同步按预期进行:

public class ThreadExample implements Runnable {
    public static void main(String args[]) {
        System.out.println("A");
        Thread T = new Thread(new ThreadExample());
        Thread T1 = new Thread(new ThreadExample());
        System.out.println("B");
        T.setName("thread 1");
        T1.setName("thread 2");
        System.out.println("C");
        T.start();
        System.out.println("D");
        T1.start();
    }

    public void run() {
        synchronized (ThreadExample.class) {
            for (int i = 0; i < 5; i++) {
                try {
                    System.out.println("Inside run=>"
                            + Thread.currentThread().getName());
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

您的问题是,如果两个同步块未锁定在同一监视器上,则它们不是互斥的。

请记住,同步方法锁定在this监视器上-您的代码等效于:

 public void run() {
    synchronized(this) {
        //your code here
    }
 }

由于您创建了ThreadExample两个实例,因此每个实例都有一个不同的this

您可以通过在两个线程中使用相同的锁来解决问题,例如:

 public void run() {
    synchronized(ThreadExample.class) {
        //your code here
    }
 }

甚至更好,只创建一个实例ThreadExample如指出Quoi

您已经创建了ThreadExample两个Object,因此每个线程都有不同的synchronized方法。

创建单个对象并将引用传递给线程,您将看到同步的效果。

ThreadExample thex = new ThreadExample();
Thread T=new Thread(thex);
Thread T1=new Thread(thex);

这里两个线程将使用相同的synchronized方法。

嗯,您正在同步每个线程的run方法。 Thread1不会尝试运行Thread2的run方法,反之亦然。 这就是为什么它实际上与根本不同步的原因相同。

您正在创建该类的两个实例,并且正在类上进行同步,因此它们将独立运行,因为没有通用锁。 他们将继续独立运行。

暂无
暂无

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

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