我們知道多線程存在一些安全性問題,java為多線程提供給了一個解決多線程安全問題的關鍵字synchronized。
### 同步的前提
1、具有兩個及以上的線程
2、必須是多個線程使用同一個鎖
java提供了Synchronized來解決多線程的安全性問題。
好處:可以解決多線程的安全問題
弊端:每次都要判斷鎖,耗費系統資源。
### 同步代碼塊
synchronized(對象){
//需要加鎖的代碼塊..
}
這個例子演示同步的作用及意義。
~~~
public class DemoSync{
public static void main(String args[]){
DemoRunnable dr = new DemoRunnable();
Thread t1 = new Thread(dr);
Thread t2 = new Thread(dr);
Thread t3 = new Thread(dr);
Thread t4 = new Thread(dr);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class DemoRunnable implements Runnable{
private int ticket=100;
Object obj = new Object(); //相當于傳入的對象鎖
public void run(){
while(true){
synchronized(obj){
if(ticket>0){
try{
Thread.sleep(10);
}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"--售票:"+ticket--);
}else{
System.exit(1);
}
}
}
}
}
~~~
### 同步函數的使用
**非靜態方法的同步**
即用synchronized修飾非靜態的方法。
?private synchronized void add(int m)
多線程代碼塊的對象鎖是 this,即當前對象的引用。
**靜態方法的同步**
用synchronized修飾靜態的方法
因為靜態方法進入內存以后并沒有產生對象,因此不可能是this,
通過驗證,多線程代碼塊的對象鎖是類.class.
**問題描述**
有兩個儲戶分別到銀行300元,每次存入100元,分3次存儲。分析是否存在安全性問題。
如何找問題:
1、明確哪些代碼是多線程運行代碼
2、明確共享數據
3、明確多線程運行代碼中哪些語句是操作共享數據的。
~~~
public class ThisLockDemo{
public static void main(String args[]){
MyRunnable dr = new MyRunnable();
StaMyRunnable smr = new StaMyRunnable();
Thread t1 = new Thread(smr);
Thread t2 = new Thread(smr);
t1.start();
t2.start();
}
}
class MyRunnable implements Runnable{
private int sum = 0;
public void run(){
for(int i=0;i<3;i++){
add(100);
}
}
private synchronized void add(int m){
sum += m;
System.out.println(Thread.currentThread().getName()+"存儲:"+sum);
}
}
class StaMyRunnable implements Runnable{
private static int sum = 0;
public void run(){
for(int i=0;i<3;i++){
add(100);
}
}
private static synchronized void add(int m){
sum += m;
System.out.println(Thread.currentThread().getName()+"存儲:"+sum);
}
}
~~~