多線程編程並發解決之道-線程鎖技術


實際項目中多線程技術的應用十分的廣泛,但如果程序中涉及到多個線程對同一變量的寫操作,那么就會涉及到線程安全的問題,如何解決多個線程對同一數據的並發操作呢?毫無疑問采用加鎖的方式解決線程並發問題是目前解決多線程並發問題的主要技術,下面來介紹一下java傳統加鎖方式和java5的線程鎖技術。

在java傳統的加鎖技術中synchronized是實現線程互斥的關鍵,根據加鎖粒度的粗細,該關鍵字可以加在方法級別上,也可以加在代碼塊級別上,根據業務需要可以自定義加鎖范圍,它的實現代碼可以是這樣的:


public class TranditionalThreadSynchronized {

public static void main(String[] args){
new TranditionalThreadSynchronized().init();
}

private void init(){
final Outputer outputer = new Outputer();
new Thread(new Runnable(){
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outputer.output("zhangsan");

}

}
}).start();


new Thread(new Runnable(){
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outputer.output("lisi");

}

}
}).start();
}
class Outputer{
public void output(String name){
int len = name.length();
synchronized(this){
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
}
簡單分析一下代碼可以在init方法中開啟了兩個線程,這兩個線程擁有對同一個Outputer對象的引用,也正是因為這個原因所以才產生了線程並發的問題,如果他們所持有的是兩個不同的Outputer對象則不會出現並發問題。從代碼中可以看出傳統的線程互斥技術通過對代碼塊進行加鎖來保持數據的安全性。針對java這種純面向對象的語言結合現實生活中的真實場景鎖更應該通過對象來體現,所以在java5中的所對象應運而生。下面改造一下代碼,來看看java5是如何通過面向對象的思想保證線程安全的:


public class LockTest {

public static void main(String[] args){
new LockTest().init();
}

private void init(){
final Outputer outputer = new Outputer();
new Thread(new Runnable(){
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outputer.output("zhangxiaoxiang");

}

}
}).start();


new Thread(new Runnable(){
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outputer.output("lihuoming");

}

}
}).start();
}
class Outputer{
Lock lock = new ReentrantLock();
public void output(String name){
int len = name.length();
//synchronized(this){
lock.lock();
try{
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}finally{
lock.unlock();
}

//}
}
}
}
對比這兩種加鎖方式,可以簡單的歸納一下在傳統的加鎖方式中,是通過外部加鎖實現的也就是鎖這個概念並不具體的隸屬於執行對象,它是一把公用所,任何對象都可以使用這把公用鎖來鎖住需要做並發處理的代碼,而java5中的線程鎖技術明顯更加面向對象化了,每一個執行對象都擁有一把屬於自己的鎖,用自己的鎖給需要進行並發處理的代碼進行加鎖和解鎖操作,但無論是哪種方式加鎖的思想是不變的,如果兩個線程需要需要做互斥操作那么他們必須要用同一把鎖才能達到互斥效果。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com