synchronized互斥鎖實例解析
阿新 • • 發佈:2019-01-21
輸出結果 cast exception 例子 輸出 itcast huang printer ron
目錄
- synchronized互斥鎖實例解析
- 1、互斥鎖基礎使用:防止多個線程訪問對象的synchronized方法。
- 1.1、不加互斥鎖時
- 1.2、加互斥鎖後
- 2、臟讀
- 2.1、不加鎖
- 2.2、加鎖後
- 1、互斥鎖基礎使用:防止多個線程訪問對象的synchronized方法。
java的內置鎖:每個java對象都可以用做一個實現同步的鎖,這些鎖成為內置鎖。線程進入同步代碼塊或方法的時候會自動獲得該鎖,在退出同步代碼塊或方法時會釋放該鎖。獲得內置鎖的唯一途徑就是進入這個鎖的保護的同步代碼塊或方法。
java內置鎖是一個互斥鎖。
對象鎖是用於對象實例方法,或者一個對象實例上的
類鎖是用於類的靜態方法或者一個類的class對象上的。
synchronized互斥鎖實例解析
1、互斥鎖基礎使用:防止多個線程訪問對象的synchronized方法。
只要一個線程訪問了其中的一個synchronized方法,其它線程不能同時訪問這個對象中任何一個synchronized方法)。
1.1、不加互斥鎖時
public class MyThread { public static void main(String[] args) { MyThread s = new MyThread(); s.thread(); } public void thread() { final Printer p = new Printer(); new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(10); p.print("1111111111"); } catch (Exception e) { } } } }, "t1").start(); new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(10); p.print("2222222222"); } catch (Exception e) { } } } }, "t2").start(); } class Printer { //synchronized public void print(String str) { // synchronized(this){ for (int i = 0; i < str.length(); i++) { System.out.print(str.charAt(i)); } System.out.println(); System.out.println("上面執行的是線程:" + Thread.currentThread().getName()); // } } } }
輸出結果片斷:
1111111111 上面執行的是線程:t1 2222222222 上面執行的是線程:t2 1111111111 上面執行的是線程:t1 2222222222 上面執行的是線程:t2 11122222221111111222 上面執行的是線程:t2 上面執行的是線程:t1 2111222222222 上面執行的是線程:t2 1111111 上面執行的是線程:t1 2222222222 上面執行的是線程:t2 1111111111 上面執行的是線程:t1 12111111111222222222 上面執行的是線程:t2 上面執行的是線程:t1 1111111111 上面執行的是線程:t1 2222222222 上面執行的是線程:t2
1.2、加互斥鎖後
package cn.itcast_01_mythread.thread.thread;
/*
* 線程安全問題
*/
public class MyThread {
public static void main(String[] args) {
MyThread s=new MyThread();
s.thread();
}
public void thread(){
final Printer p=new Printer();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try{
Thread.sleep(10);
p.print("1111111111");
}catch(Exception e){
}
}
}
},"t1").start();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try{
Thread.sleep(10);
p.print("2222222222");
}catch(Exception e){
}
}
}
},"t2").start();
}
class Printer{
//synchronized
public synchronized void print(String str){
// synchronized(this){
for(int i=0;i<str.length();i++){
System.out.print(str.charAt(i));
}
System.out.println();
System.out.println("上面執行的是線程:"+Thread.currentThread().getName());
// }
}
}
}
輸出結果:不會出現錯位位置
2222222222
上面執行的是線程:t2
1111111111
上面執行的是線程:t1
2222222222
上面執行的是線程:t2
1111111111
上面執行的是線程:t1
2222222222
上面執行的是線程:t2
1111111111
上面執行的是線程:t1
2222222222
上面執行的是線程:t2
1111111111
上面執行的是線程:t1
2222222222
上面執行的是線程:t2
1111111111
2、臟讀
2.1、不加鎖
2.1.1、例子1,兩個方法都不加鎖
package cn.itcast_01_mythread.thread.thread;
/*
* 臟讀
*/
public class Dirty_read_4 {
private String weibo_name = "angel" ;
private String weibo_sex = "女" ;
//synchronized
public void setValue(String weibo_name , String weibo_sex){
this.weibo_name = weibo_name ;
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.weibo_sex = weibo_sex ;
System.out.println("setValue---------weibo_name :" + weibo_name + "-- weibo_sex : "+weibo_sex);
}
public void getValue(){
System.out.println("getValue---------weibo_name :" + weibo_name + "-- weibo_sex : "+weibo_sex);
}
public static void main(String[] args) throws InterruptedException {
final Dirty_read_4 dr = new Dirty_read_4();
Thread t1 = new Thread(new Runnable() {
public void run() {
dr.setValue("huangxiaoming" , "男");
}
}) ;
t1.start();
Thread.sleep(1000);
dr.getValue();
}
}
輸出結果:順序混亂
getValue---------weibo_name :huangxiaoming-- weibo_sex : 女
setValue---------weibo_name :huangxiaoming-- weibo_sex : 男
2.1.2、例子1,getValue不加鎖
package cn.itcast_01_mythread.thread.thread;
/*
* 臟讀
*/
public class Dirty_read_4 {
private String weibo_name = "angel" ;
private String weibo_sex = "女" ;
//synchronized
public synchronized void setValue(String weibo_name , String weibo_sex){
this.weibo_name = weibo_name ;
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.weibo_sex = weibo_sex ;
System.out.println("setValue---------weibo_name :" + weibo_name + "-- weibo_sex : "+weibo_sex);
}
//TODO synchronized
public void getValue(){
System.out.println("getValue---------weibo_name :" + weibo_name + "-- weibo_sex : "+weibo_sex);
}
public static void main(String[] args) throws InterruptedException {
final Dirty_read_4 dr = new Dirty_read_4();
Thread t1 = new Thread(new Runnable() {
public void run() {
dr.setValue("huangxiaoming" , "男");
}
}) ;
t1.start();
Thread.sleep(1000);
dr.getValue();
}
}
輸出結果:順序混亂
getValue---------weibo_name :huangxiaoming-- weibo_sex : 女
setValue---------weibo_name :huangxiaoming-- weibo_sex : 男
2.2、加鎖後
能夠保證,執行順序按照main方法的調用順序依次執行。
sleep是帶鎖沈睡。
package cn.itcast_01_mythread.thread.thread;
/*
* 臟讀
*/
public class Dirty_read_4 {
private String weibo_name = "angel" ;
private String weibo_sex = "女" ;
//synchronized
public synchronized void setValue(String weibo_name , String weibo_sex){
this.weibo_name = weibo_name ;
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.weibo_sex = weibo_sex ;
System.out.println("setValue---------weibo_name :" + weibo_name + "-- weibo_sex : "+weibo_sex);
}
//TODO synchronized
public synchronized void getValue(){
System.out.println("getValue---------weibo_name :" + weibo_name + "-- weibo_sex : "+weibo_sex);
}
public static void main(String[] args) throws InterruptedException {
final Dirty_read_4 dr = new Dirty_read_4();
Thread t1 = new Thread(new Runnable() {
public void run() {
dr.setValue("huangxiaoming" , "男");
}
}) ;
t1.start();
Thread.sleep(1000);
dr.getValue();
}
}
輸出結果:
setValue---------weibo_name :huangxiaoming-- weibo_sex : 男
getValue---------weibo_name :huangxiaoming-- weibo_sex : 男
synchronized互斥鎖實例解析