內容
1.synchronized工作原理
2.synchronized修飾方法
3.一個小面試題(輸出結果目前看不懂)
4.類鎖
5.死鎖
一.synchronized的工作原理
synchronized(this){}
t1線程執行到此處,遇到了synchronized關鍵字,就會去找this的對象鎖,如果找到this對象鎖,則進入同步語句塊中執行程序,當同步語句塊中的代碼執行結束之后,t1線程歸還this的對象鎖。
在t1線程執行同步語句塊的過程中,如果t2線程也過來執行這些代碼,也遇到synchronized關鍵字,所以也去找this的對象鎖,但是該對象鎖被t1線程持有,只能在這等待this對象的歸還
二.synchronized修飾方法
使用示例
public synchronized void withdraw(double money) {
double after = balance - money;
//延遲
try{Thread.sleep(1000);}catch(Exception e) {}
//更新余額
this.setBalance(after);
}
當synchronized關鍵字添加到成員方法上的時候,線程拿走的也是this的對象鎖。但是這種方式不推薦,不如前面那一種同步的更精細
三.一個小面試題(輸出結果目前看不懂)
/*
* 面試題
*/
public class 測試程序 {
public static void main(String[] args) throws InterruptedException {
//創建mc對象
MyClass mc = new MyClass();
Processor p = new Processor(mc);
//創建線程t1,t2并命名
Thread t1 = new Thread(p);
t1.setName("t1");
Thread t2 = new Thread(p);
t2.setName("t2");
//啟動線程
t1.start();
//延遲(保證t1先啟動,并執行run)
Thread.sleep(1000);
t2.start();
}
}
//創建線程
class Processor implements Runnable
{
MyClass mc;
Processor(MyClass mc){
this.mc = mc;
}
public void run() {
//如果是t1線程,就執行m1
if(Thread.currentThread().getName().equals("t1"));{
mc.m1();
}
//如果是t2線程,就執行m2
if(Thread.currentThread().getName().equals("t2")) {
mc.m2();
}
}
}
class MyClass{
public synchronized void m1() {
//休眠
try {
Thread.sleep(2000);
}catch(Exception e) {}
System.out.println("m1");
}
//m2方法會等m1方法結束,t1,t2共享同一個mc,并且m1和m2方法上都有synchronized
public synchronized void m2() {
System.out.println("m2");
}
}
上面這個程序本應該輸出
m1
m2
但是實際上輸出了
m1
m1
m2
想了好久也不知道什么原因。
剛才講的是對象鎖,下面講類鎖
四.類鎖
1.如何使用
synchronized添加到靜態方法上,線程執行此方法的時候會找類鎖
2.使用示例
public class 測試程序 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Processor());
Thread t2 = new Thread(new Processor());
t1.setName("t1");
t2.setName("t2");
t1.start();
//延遲,保證t1先執行
Thread.sleep(1000);
t2.start();
}
}
//創建線程
class Processor implements Runnable
{
public void run() {
if("t1".equals(Thread.currentThread().getName())) {
MyClass.m1();
}
if("t2".equals(Thread.currentThread().getName())) {
MyClass.m2();
}
}
}
class MyClass{
//synchronized添加到靜態方法上,線程執行此方法的時候會找類鎖
public synchronized static void m1() {
try {
Thread.sleep(10000);
}catch(Exception e) {}
System.out.println("m1...");
}
//不會等m1結束,因為該方法沒有被synchronized修飾
/*public static void m2() {
System.out.println("m2...");
}
*/
//這個m2方法會等m1方法結束之后才執行,因為該方法有synchronized
//線程執行該代碼需要類鎖,而類鎖只有一個
public synchronized static void m2() {
System.out.println("m2...");
}
}
就會輸出
m1...
m2...
五.死鎖
public class 測試程序 {
public static void main(String[] args) throws InterruptedException {
Object o1 = new Object();
Object o2 = new Object();
Thread t1 = new Thread(new T1(o1,o2));
Thread t2 = new Thread(new T2(o1,o2));
t1.start();
t2.start();
}
}
class T1 implements Runnable{
Object o1;
Object o2;
T1(Object o1,Object o2){
this.o1 = o1;
this.o2 = o2;
}
public void run() {
synchronized(o1) {
try{Thread.sleep(1000);}catch(Exception e) {}
synchronized(o2) {
}
}
}
}
class T2 implements Runnable{
Object o1;
Object o2;
T2(Object o1,Object o2){
this.o1 = o1;
this.o2 = o2;
}
public void run() {
synchronized(o2) {
try {
Thread.sleep(1000);
}catch(Exception e) {}
synchronized(o1) {
}
}
}
}
這個程序就進入一個僵持狀態
t1剛鎖住o1,準備鎖o2時,o2已經被t2鎖住,此時t2還想鎖o1