Java 中的 synchronized 关键字

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_38737992/article/details/89576078

synchronized 关键字用来同步“方法”或者“代码块”,可以实现原子性,可见性,有序性。采取互斥机制,即在同一时刻,只能有一个线程访问同步资源,串行的执行“方法”或者“代码块”。

缺点:缺点降低了线程的并发性;不能中断;多个锁交叉容易死锁。

 1. 问题的引出

多个线程在共享一个数据的时候会出现问题,如下所示,多个线程共同访问一个变量。

package synchronizedStudy;

public class MyStudy implements Runnable {
    private int count;

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.print(Thread.currentThread().getName() + ": ");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(++count);
        }
    }

    public static void main(String args[]) {
        MyStudy runn = new MyStudy();
        Thread thread1 = new Thread(runn, "thread1");
        Thread thread2 = new Thread(runn, "thread2");
        Thread thread3 = new Thread(runn, "thread3");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

运行结果如下所示,共享变量出现了重复值。

2. synchronized 关键字同步“代码块”解决问题

synchronized 关键字用来同步“代码块”,即在同一时刻,只能有一个线程访问同步资源,串行的执行“代码块”。

先声明一个静态常量对象:

public final static Object Mutex = new Object();

对应代码块加锁,这个代码块在同一时刻,只能有一个线程执行这段代码:

            synchronized (Mutex) {
                System.out.print(Thread.currentThread().getName() + ": ");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(++count);
            }

 全部代码如下所示:

package synchronizedStudy;

public class MyStudy implements Runnable {
    private int count;
    public final static Object Mutex = new Object();

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            this.work();
        }
    }


    public void work() {
        synchronized (Mutex) {
            System.out.print(Thread.currentThread().getName() + ": ");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(++count);
        }
    }

    public static void main(String args[]) {
        MyStudy runn = new MyStudy();
        Thread thread1 = new Thread(runn, "thread1");
        Thread thread2 = new Thread(runn, "thread2");
        Thread thread3 = new Thread(runn, "thread3");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

运行结果:

3. synchronized 关键字同步“方法”解决问题

synchronized 关键字用来同步“方法”,即在同一时刻,只能有一个线程访问同步资源,串行的执行“方法”。

    public synchronized void work() {
        System.out.print(Thread.currentThread().getName() + ": ");
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(++count);
    }

全部代码如下所示:

package synchronizedStudy;

public class MyStudy implements Runnable {
    private int count;

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            this.work();
        }
    }


    public synchronized void work() {
        System.out.print(Thread.currentThread().getName() + ": ");
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(++count);
    }

    public static void main(String args[]) {
        MyStudy runn = new MyStudy();
        Thread thread1 = new Thread(runn, "thread1");
        Thread thread2 = new Thread(runn, "thread2");
        Thread thread3 = new Thread(runn, "thread3");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

运行截图:

4. 多个锁交叉容易死锁

如下所示,锁READ和锁WRITE交叉:

public void work() {
    synchronized (READ) {
        synchronized (WRITE) {
            ...
    }
}

public void work1() {
    synchronized (WRITE) {
        synchronized (READ) {
            ...
    }
}


全部代码:

package synchronizedStudy;

public class MyStudy implements Runnable {
    private int count;
    public final static Object READ = new Object();
    public final static Object WRITE = new Object();

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            this.work();
            this.work1();
        }
    }


    public void work() {
        synchronized (READ) {
            synchronized (WRITE) {
                System.out.print(Thread.currentThread().getName());
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void work1() {
        synchronized (WRITE) {
            synchronized (READ) {
                System.out.println(Thread.currentThread().getName());
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String args[]) {
        MyStudy runn = new MyStudy();
        Thread thread1 = new Thread(runn, "thread1");
        Thread thread2 = new Thread(runn, "thread2");
        Thread thread3 = new Thread(runn, "thread3");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

运行结果,发生了死锁:

猜你喜欢

转载自blog.csdn.net/qq_38737992/article/details/89576078