synchronized互斥锁实例解析

Posted amunamuna

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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互斥锁实例解析的主要内容,如果未能解决你的问题,请参考以下文章

synchronized学习

Synchronized理解及用法

ReentrantLock锁与内置锁synchronized

ReentrantLock锁与内置锁synchronized

ReentrantReadWriteLock场景应用

011 深入理解synchronized