Java synchronized关键字

1. synchronized关键字

synchronized用于实现同步操作,防止出现脏读,常用于修饰方法和代码块。

2. synchronized同步

synchronized用于修饰方法时,线程锁的对象是其自身,等同于synchronized(this){}代码块,也等同于synchronized(锁对象){}

public class ObjectLock {

    public synchronized void methodA() {
        System.out.println(Thread.currentThread().getName() + ": methodA begin");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
        System.out.println(Thread.currentThread().getName() + ": methodA end");
    }

    public void methodB() {
        synchronized (this) {
            System.out.println(Thread.currentThread().getName() + ": methodB begin");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            System.out.println(Thread.currentThread().getName() + ": methodB end");
        }
    }

    public static class ThreadA extends Thread {
        ObjectLock lock;

        ThreadA(ObjectLock lock) {
            this.lock = lock;
            setName("A");
        }

        @Override
        public void run() {
            lock.methodA();
        }
    }

    public static class ThreadB extends Thread {
        ObjectLock lock;

        ThreadB(ObjectLock lock) {
            this.lock = lock;
            setName("B");
        }

        @Override
        public void run() {
            lock.methodB();
        }
    }

    public static class ThreadC extends Thread {
        ObjectLock lock;

        ThreadC(ObjectLock lock) {
            this.lock = lock;
            setName("C");
        }

        @Override
        public void run() {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + ": methodC begin");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                }
                System.out.println(Thread.currentThread().getName() + ": methodC end");
            }	
        }
    }

}

分别调用这三个线程

public static void main(String[] args) {
    ObjectLock lock = new ObjectLock();

    ThreadA threadA = new ThreadA(lock);
    threadA.start();

    ThreadB threadB = new ThreadB(lock);
    threadB.start();

    ThreadC threadC = new ThreadC(lock);
    threadC.start();
}

输出
在这里插入图片描述
对象锁有几个注意点

  • 不同的对象拥有不同的锁,相互之间是不同步的。

  • 同步不具有继承性,子类的覆盖方法需要添加synchronized关键字。

  • 多线程死锁问题,线程ThreadAThreadB分别拥有lock1lock2,当ThreadA在请求lock2ThreadB在请求lock1时都将形成死锁,导致程序无法继续进行。

    public class DeadLock {
    
        public static void main(String[] args) {
            DeadLock lock1 = new DeadLock();
            DeadLock lock2 = new DeadLock();
    
            ThreadA threadA = new ThreadA(lock1, lock2);
            threadA.start();
    
            ThreadB threadB = new ThreadB(lock1, lock2);
            threadB.start();
        }
    
        public static class ThreadA extends Thread {
            DeadLock lock1, lock2;
    
            public ThreadA(DeadLock lock1, DeadLock lock2) {
                this.lock1 = lock1;
                this.lock2 = lock2;
                setName("A");
            }
    
            @Override
            public void run() {
                synchronized (lock1) {
                    System.out.println(Thread.currentThread().getName() + ": methodA begin");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                    }
    
                    synchronized (lock2) {
                        System.out.println(Thread.currentThread().getName() + ": methodAA");
                    }
                    System.out.println(Thread.currentThread().getName() + ": methodA end");
                }
            }
        }
    
        public static class ThreadB extends Thread {
            DeadLock lock1, lock2;
    
            public ThreadB(DeadLock lock1, DeadLock lock2) {
                this.lock1 = lock1;
                this.lock2 = lock2;			
                setName("B");
            }
    
            @Override
            public void run() {
                synchronized (lock2) {
                    System.out.println(Thread.currentThread().getName() + ": methodB begin");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                    }
    
                    synchronized (lock1) {
                        System.out.println(Thread.currentThread().getName() + ": methodBB");
                    }
                    System.out.println(Thread.currentThread().getName() + ": methodB end");
                }
            }
    
        }
    
    }
    

3. synchronized静态同步

对静态方法添加同步操作,等同于等同于synchronized(对象对应Class类){}代码块。

public class StaticLock {

    public static void main(String[] args) {
        ThreadA threadA = new ThreadA();
        threadA.start();

        ThreadB threadB = new ThreadB();
        threadB.start();
    }

    public synchronized static void methodA() {
        System.out.println(Thread.currentThread().getName() + ": methodA begin");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
        System.out.println(Thread.currentThread().getName() + ": methodA end");
    }

    public static class ThreadA extends Thread {

        ThreadA() {        
            setName("A");
        }

        @Override
        public void run() {
            StaticLock.methodA();
        }
    }

    public static class ThreadB extends Thread {

        ThreadB() {
            setName("B");
        }

        @Override
        public void run() {
            synchronized (StaticLock.class) {
                System.out.println(Thread.currentThread().getName() + ": methodB begin");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                }
                System.out.println(Thread.currentThread().getName() + ": methodB end");
            }
        }
    }
}

输出
在这里插入图片描述

4. synchronized和volatile

  • synchronized解决了多个线程之间访问资源的同步性。
  • volatile增加了变量在多个线程之间的可见性,但不具备同步性,也不支持原子性。

例如SyncLock有一个变量condition,分别在不同线程中修改它

public class SyncLock {

    private boolean condition = true;

    public void methodA() {
        System.out.println(Thread.currentThread().getName() + ": methodA begin");
        while(condition) {
        }
        System.out.println(Thread.currentThread().getName() + ": methodA end");
    }

    public void stopMethodA() {
        condition = false;
    }

    public static class ThreadA extends Thread {
        SyncLock lock;

        ThreadA(SyncLock lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            lock.methodA();
        }
    }

    public static class ThreadB extends Thread {
        SyncLock lock;

        ThreadB(SyncLock lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
            lock.stopMethodA();
        }
    }

}

测试代码,

public static void main(String[] args) {
    SyncLock lock = new SyncLock();

    ThreadA threadA = new ThreadA(lock);
    threadA.start();

    ThreadB threadB = new ThreadB(lock);
    threadB.start();
}

methodA()会一直在运行(如果不是,改用-server服务器模式运行),除非使用volatile关键字改变condition的可见性。

private volatile boolean condition = true;

synchronized同样可以使不同线程进入同步方法或同步代码块后,具有可视性。

public void methodA() {
    System.out.println(Thread.currentThread().getName() + ": methodA begin");
    while(condition) {
        synchronized (this) {
        }
    }
    System.out.println(Thread.currentThread().getName() + ": methodA end");
}

相关文章
Java synchronized关键字
Java 关键字strictfp、volatile和transient

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值