1. 程式人生 > >synchronized互斥鎖實例解析

synchronized互斥鎖實例解析

輸出結果 cast exception 例子 輸出 itcast huang printer ron

目錄

  • synchronized互斥鎖實例解析
    • 1、互斥鎖基礎使用:防止多個線程訪問對象的synchronized方法。
      • 1.1、不加互斥鎖時
      • 1.2、加互斥鎖後
    • 2、臟讀
      • 2.1、不加鎖
      • 2.2、加鎖後

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互斥鎖實例解析