二(Synchronized)的对象锁

学习笔记:来源慕课网 https://www.imooc.com/learn/1086

Synchronized methods enable a simple strategy for preventing thread interference and memory consistency errors : if an object is visible to more than one thread ,all reads or writes to that object's variables are done throught synchronized methods

同步方法支持的一种简单的策瑜来防止线程干扰和内存一致性错误,如果一个对象对多个线程可见,则对该对象变量的所有读取或写入都是通过同步方法完成的。

synchronized 的作用

能够保证在同一时刻最多只有一个线程执行该段代码,以达到保证并发安全的效果。

synchronized 是java 的关键字,被java 语言原生支持。
是最基本互斥同步手段。
是并发编程中的元老级别角色,是并发编程的必学内容。

不使用并发手段会有什么后果。
代码实战:两个线程同时a++ ,最后结果会比预计的少。

上代码:一



/**
 * @author sxylml
 * @Date : 2019/2/25 16:47
 * @Description:
 * 消失的请求
 * 不采用并发控制,执行结果就不是我们所预计的效果。
 * 

* 原因:count ++ 看上去是一个操作,实际上包含三个动作 * 1:读取count * 2: 将count +1 * 3:将count 的值写入内存 */ public class DisappearRequest implements Runnable { static DisappearRequest instance = new DisappearRequest(); static int count = 0; public static void main(String[] args) { Thread thread1 = new Thread(instance); Thread thread2 = new Thread(instance); thread1.start(); thread2.start(); try { thread1.join(); thread2.join(); System.out.println(count); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public void run() { for (int i = 0; i < 100000; i++) { // 不加锁运行结果基本都是小于 200000 // synchronized (this){ count++; // } } } }

二(Synchronized)的对象锁_第1张图片
image.png

synchronized 的两个用法
对象锁:包括方法锁,(默认对象为this为当前实例对象)和同步代码块(自己指定锁对象)
类锁:指synchronized修饰静态的方法或指定锁为Class 对象

第一个用法:
对象锁


/**
 * @author sxylml
 * @Date : 2019/2/25 16:55
 * @Description: 对象锁
 * 对象锁形式1.代码块形式,如果没有加锁,则运行结果,线程结束顺序就不确定
 */
public class SynchronizedObjectCodeBlack implements Runnable {
    static SynchronizedObjectCodeBlack instance = new SynchronizedObjectCodeBlack();
    @Override
    public void run() {
        String threadName = Thread.currentThread().getName();
        System.out.println("我是对象锁的代码块形式。我叫" + threadName);
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("我是对象锁的代码块形式。我叫" + threadName+ "运行结束!");
    }
    public static void main(String[] args) {
        Thread thread1 = new Thread(instance);
        Thread thread2 = new Thread(instance);
        Thread thread3 = new Thread(instance);

        thread1.start();
        thread2.start();
        thread3.start();

        while (thread1.isAlive() || thread2.isAlive() || thread3.isAlive()) {

        }
        System.out.println("结束程序");

    }
}
二(Synchronized)的对象锁_第2张图片
image.png

/**
 * @author sxylml
 * @Date : 2019/2/25 16:55
 * @Description: 对象锁
 * 对象锁形式1.代码块形式,加锁,则运行结果,线程开始-结束 都是顺序执行的
 */
public class SynchronizedObjectCodeBlack implements Runnable {
    static SynchronizedObjectCodeBlack instance = new SynchronizedObjectCodeBlack();
    @Override
    public void run() {
    // 当前对象做为锁
        synchronized (this) {
            String threadName = Thread.currentThread().getName();
            System.out.println("我是对象锁的代码块形式。我叫" + threadName);
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("我是对象锁的代码块形式。我叫" + threadName + "运行结束!");
        }
    }
    public static void main(String[] args) {
        Thread thread1 = new Thread(instance);
        Thread thread2 = new Thread(instance);
        Thread thread3 = new Thread(instance);

        thread1.start();
        thread2.start();
        thread3.start();

        while (thread1.isAlive() || thread2.isAlive() || thread3.isAlive()) {

        }
        System.out.println("结束程序");

    }
}

二(Synchronized)的对象锁_第3张图片
image.png

·

使用自己创建的对象加锁:




/**
 * @author sxylml
 * @Date : 2019/2/26 09:09
 * @Description: 保护时机不相同的情况,可以使用2个锁...
 */
public class SynchronizedObjectCode implements Runnable {


    Object lock1 = new Object();
    Object lock2 = new Object();

    @Override
    public void run() {


        synchronized (lock1) {
            System.out.println("我是lock1 的代码块形式:我叫" + Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() +"  lock1运行结束");
        }
        synchronized (lock2) {
            System.out.println("我是lock2 的代码块形式:我叫" + Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() +" lock2 运行结束");
        }






    }

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        Runnable instance = new SynchronizedObjectCode();

        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);

        t1.start();
        t2.start();
        while (t1.isAlive() || t2.isAlive()) {

        }
        long endTime = System.currentTimeMillis();
        System.out.println("finished 用时:" + (endTime - startTime));

    }
}

二(Synchronized)的对象锁_第4张图片
image.png

/**
 * @author sxylml
 * @Date : 2019/2/26 09:29
 * @Description: synchronized 修饰方式
 */
public class SynchronizedObjectMethod implements Runnable {


    @Override
    public void run() {
        method();

    }

    public synchronized void method() {

        System.out.println("对象锁的方法修饰符形式,我叫:" + Thread.currentThread().getName());

        try {
            System.out.println(Thread.currentThread().getName() + " 休眠3秒");
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "运行结束");

    }


    public static void main(String[] args) {
        Long startTime = System.currentTimeMillis();
        Runnable instance = new SynchronizedObjectMethod();

        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);

        t1.start();
        t2.start();

        while (t1.isAlive() || t2.isAlive()) {

        }

        Long endTime = System.currentTimeMillis();
        System.out.println("整个程序运行结束! 用时" + (endTime - startTime));

    }
}

二(Synchronized)的对象锁_第5张图片
image.png

结果会是:顺序执行完毕。
总结:

第一个用法:对象锁
代码块形式:手动指定锁对象
方法锁形式:synchronized 修饰普通方法,锁对象默认为this,不能是静态方法哦。

你可能感兴趣的:(二(Synchronized)的对象锁)