基本介紹:
Synchronized是Java中解決併發問題的一種最常用的方法,也是最簡單的一種方法。
主要作用:
- 修飾普通方法
- 修飾靜態方法
- 修飾代碼塊
代碼演示:
1.無Synchronized修飾
public class SyTestDemo {
public void methods1(){
System.out.println("methods1.start..");
try {
System.out.println("methods1.excute..");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("methods1.end..");
}
public void methods2(){
System.out.println("methods2.start.." );
try {
System.out.println("methods2.excute..");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("methods2.end..");
}
public static void main(String[] args) {
SyTestDemo testDemo = new SyTestDemo();
new Thread(new Runnable() {
@Override
public void run() {
testDemo.methods1();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
testDemo.methods2();
}
}).start();
}
}
結果:
可以看出線程2在線程1結束前先結束。沒有達到線程1運行完然後線程2在運行的目的。
2.修飾普通方法
代碼演示
public class SyTestDemo2 {
//方法塊1
public synchronized void methods1(){
System.out.println("methods1.start..");
try {
System.out.println("methods1.excute..");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("methods1.end..");
}
//方法塊2
public synchronized void methods2(){
System.out.println("methods2.start..");
try {
System.out.println("methods2.excute..");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("methods2.end..");
}
public static void main(String[] args) {
SyTestDemo2 syTestDemo2 = new SyTestDemo2();
new Thread(new Runnable() {
@Override
public void run() {
syTestDemo2.methods1();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
syTestDemo2.methods2();
}
}).start();
}
}
結果:
可以看出結果中是線程1先執行完然後線程2再完成。沒有併發執行的情況產生。
3.修飾靜態方法
代碼演示:
public class SyTestDemo2 {
//靜態方法1
public static synchronized void methods1(){
System.out.println("methods1.start..");
try {
System.out.println("methods1.excute..");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("methods1.end..");
}
//靜態方法2
public static synchronized void methods2(){
System.out.println("methods2.start..");
try {
System.out.println("methods2.excute..");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("methods2.end..");
}
public static void main(String[] args) {
SyTestDemo2 syTestDemo2 = new SyTestDemo2();
new Thread(new Runnable() {
@Override
public void run() {
syTestDemo2.methods1();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
syTestDemo2.methods2();
}
}).start();
}
}
結果:
修飾靜態方法相當於修飾類。因爲靜態方法是類的方法而不是對象的方法。所以輸出結果依舊是線程1先執行完,然後線程2執行完,沒有併發執行。
4.修飾對象。
public class SyTestDemo3 {
//方法塊1
public void methods1(){
System.out.println("methods1.start..");
synchronized (this){
System.out.println("methods1.excute..");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("methods1.end..");
}
//方法塊2
public void methods2(){
System.out.println("methods2.start..");
synchronized (this){
System.out.println("methods2.excute..");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("method2.end..");
}
public static void main(String[] args) {
SyTestDemo3 syTestDemo3 = new SyTestDemo3();
new Thread(new Runnable() {
@Override
public void run() {
syTestDemo3.methods1();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
syTestDemo3.methods2();
}
}).start();
}
}
結果:
可以從結果中看出:雖然線程1和線程2都進入方法執行。但是線程2在進入同步塊之前,需要等待線程1中同步塊執行完成。
參考博客:Sychronized的學習和底層實現