java中每一個對象都會有一個對象鎖,而synchronized就是獲得這個鎖,看下面這個例子java
import java.util.Random; public class MyData{ public synchronized void increment() { for (int i = 0; i < 10; i++) { try { Thread.sleep(new Random().nextInt(200)); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":" +i); } } public synchronized void decrement() { for (int i = 0; i < 10; i++) { try { Thread.sleep(new Random().nextInt(200)); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":" +i); } } public static void main(String[] args) { final MyData myData1 = new MyData(); // final MyData myData2 = new MyData(); new Thread(new Runnable() { @Override public void run() { myData1.increment(); } }).start(); new Thread(new Runnable() { @Override public void run() { myData1.decrement(); } }).start(); } }
不管執行多少次都是有序的,兩個線程操做的是同一個對象,第一個執行的線程獲得了鎖,第二個線程只能等第一個線程執行完了才能拿到鎖,進入方法。dom
再看下面這個例子ide
import java.util.Random; public class MyData{ public synchronized void increment() { for (int i = 0; i < 10; i++) { try { Thread.sleep(new Random().nextInt(200)); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":" +i); } } public synchronized void decrement() { for (int i = 0; i < 10; i++) { try { Thread.sleep(new Random().nextInt(200)); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":" +i); } } public static void main(String[] args) { final MyData myData1 = new MyData(); final MyData myData2 = new MyData(); new Thread(new Runnable() { @Override public void run() { myData1.increment(); } }).start(); new Thread(new Runnable() { @Override public void run() { myData2.decrement(); } }).start(); } }
執行的結果是無序的,兩個對象,兩把鎖,故互不影響,各自執行各自的。spa
再來看看下面這個例子線程
import java.util.Random;
public class MyData{
public synchronized void increment() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(new Random().nextInt(200));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" +i);
}
}
public static synchronized void decrement() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(new Random().nextInt(200));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" +i);
}
}
public static void main(String[] args) {
final MyData myData1 = new MyData();
// final MyData myData2 = new MyData();
new Thread(new Runnable() {
@Override
public void run() {
myData1.increment();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
MyData.decrement();
}
}).start();
}
}
結果也是無序的,緣由和上面同樣,static方法是屬於Class對象的,故decrement方法鎖的MyData.Class對象,而myData1.increment();鎖的是myData1對象,互不干擾。code
只需記住synchronized鎖的是對象,每一個對象有一把對象鎖,拿到鎖以後才能執行synchronized的方法對象