首頁 >Java >java教程 >Java:詳細講解物件鎖定「synchronized」與全域鎖

Java:詳細講解物件鎖定「synchronized」與全域鎖

php是最好的语言
php是最好的语言原創
2018-08-03 11:20:252722瀏覽

先來看一段程式碼:

class MyThread implements Runnable{
	private int count = 10;
	@Override
	public void run() {
		while(count > 0) {
			System.out.println(Thread.currentThread().getName() + "开始执行");
			System.out.println("count还剩" + --count);
			System.out.println(Thread.currentThread().getName() + "执行结束");
			System.out.println();
		}
	}	
}

public class Test{
	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		new Thread(myThread).start();
		new Thread(myThread).start();
		new Thread(myThread).start();
	}
}

運行結果如下:

Thread-0开始执行
Thread-2开始执行
Thread-1开始执行
count还剩8
count还剩9
Thread-2执行结束
count还剩7
Thread-1执行结束

Thread-1开始执行

Thread-0执行结束

Thread-0开始执行
count还剩5
Thread-0执行结束

Thread-2开始执行
count还剩4
Thread-2执行结束

Thread-2开始执行
count还剩3
count还剩6
Thread-2执行结束

Thread-2开始执行
Thread-0开始执行
count还剩2
Thread-2执行结束

Thread-2开始执行
count还剩0
Thread-2执行结束

Thread-1执行结束

count还剩1
Thread-0执行结束

很顯然這不是我們想要的結果,我們想要的結果是:一個獨自完整地按順序跑完自己的run()方法,然而上面的結果是亂序的:上一個線程還沒跑完自己的任務,第二個線程就進來了。那麼如何來解決這個問題呢?

首先我們來分析一下,三個線程同時拿到我們自己創建的物件myThread,然後啟動這三個線程,這三個線程會同時進入這個run()方法進行執行。如果我們想要每個執行緒進入後完整的跑完自己的任務,這時候就需要把這個myThread物件鎖起來,不讓其他執行緒拿到,這樣就能實現。就比如說,有一個房間,你進去之後,不要其他人再進來,你就得把門鎖住一個道理。

在Java裡面為我們提供了一個叫做「synchronized」的鎖子。那麼它應該怎樣來使用呢?

「synchronized」的兩種模式:同步方法、同步程式碼區塊。

       一、物件鎖定:

       1、同步程式碼區塊:在程式碼區塊前方加上synchronized(要鎖定的物件)。

class MyThread implements Runnable{
	private int count = 10;
	@Override
	public void run() {
		synchronized (this) {
			while(count > 0) {
				System.out.println(Thread.currentThread().getName() + "开始执行");
				System.out.println("count还剩" + --count);
				System.out.println(Thread.currentThread().getName() + "执行结束");
				System.out.println();
			}
		}	
	}	
}

public class Test{
	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		new Thread(myThread).start();
		new Thread(myThread).start();
		new Thread(myThread).start();
	}
}

2、同步方法:在方法的回傳值前面加上synchronized關鍵字。

class MyThread implements Runnable{
	private int count = 10;
	@Override
	public void run() {
		while(count > 0) {
			count--;
			fun();
		}
	}
	public synchronized void fun() {
		System.out.println(Thread.currentThread().getName() + "开始执行");
		System.out.println("count还剩" + count);
		System.out.println(Thread.currentThread().getName() + "执行结束");
		System.out.println();
	}
}

public class Test{
	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		new Thread(myThread).start();
		new Thread(myThread).start();
		new Thread(myThread).start();
	}
}

二、全域鎖定:

在上面,我們鎖住的都是myThread對象,如果要鎖住多個物件的同一個方法又該怎麼辦呢?

這裡與物件鎖定也有兩種方法:同步方法和同步程式碼區塊。

1、同步程式碼區塊前的括號裡寫成想要鎖住的方法的類別.class

class MyThread implements Runnable{
	private static int count = 10;
	@Override
	public void run() {
		synchronized (MyThread.class) {
			while(count > 0) {
				count--;
				fun();
			}
		}	
	}
	public void fun() {
		System.out.println(Thread.currentThread().getName() + "开始执行");
		System.out.println("count还剩" + count);
		System.out.println(Thread.currentThread().getName() + "执行结束");
		System.out.println();
	}
}

public class Test{
	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		new Thread(myThread).start();
		new Thread(myThread).start();
		new Thread(myThread).start();
	}
}

2、在前面所說同步方法的基礎上,加上static關鍵字,就可以實作全域鎖。

class MyThread implements Runnable{
	private static int count = 10;
	@Override
	public void run() {
		while(count > 0) {
			fun();
		}
	}
	public synchronized static void fun() {
		System.out.println(Thread.currentThread().getName() + "开始执行");
		System.out.println("count还剩" + count);
		System.out.println(Thread.currentThread().getName() + "执行结束");
		System.out.println();
		count--;
	}
}

public class Test{
	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		new Thread(myThread).start();
		new Thread(myThread).start();
		new Thread(myThread).start();
	}
}

相關文章:

Java同步鎖定(synchronized)的範例程式碼分享

詳解Java中synchronized關鍵字的死鎖和記憶體佔用問題

相關影片:

#全面解析Java註解

以上是Java:詳細講解物件鎖定「synchronized」與全域鎖的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn