簡體   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