synchronized 锁的基本用法

1. 修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码块前要获得给定对象的锁,并且是在需要是同一个对象锁,也即创建实现Runnable接口的时候需要是同一个对象,如果创建了两个对象那么他们不属于同一个对象锁:

public class ThreadCount implements Runnable{
    private static int count = 100;

    @Override
    public void run() {
        while (true){
            cal();
        }
    }

    private void cal() {
        if (count > 1){
            // 加锁
            synchronized (this){
                count--;
                System.out.println(Thread.currentThread().getName() + " " + count);
            }
        }
    }

    public static void main(String[] args) {
        ThreadCount threadCount = new ThreadCount();
        new Thread(threadCount).start();
        new Thread(threadCount).start();
    }
}

2. 修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁:

package thread;

public class ThreadCount implements Runnable{
    private static int count = 100;

    @Override
    public void run() {
        while (true){
            cal();
        }
    }

    // 如果将synchronized加到实例方法上则使用this锁, 等同于之前的写法, 所以一般在方法上加上锁会比较方便一点
    private synchronized void cal() {
        if (count > 1){
            count--;
            System.out.println(Thread.currentThread().getName() + " " + count);
        }
    }

    public static void main(String[] args) {
        ThreadCount threadCount = new ThreadCount();
        new Thread(threadCount).start();
        new Thread(threadCount).start();

    }
}

3. 如果将synchronized加到静态方法上,默认使用当前的类名.class:

package thread;

public class ThreadCount implements Runnable{
    private static int count = 100;

    @Override
    public void run() {
        while (true){
            cal();
        }
    }

    // 如果将synchronized加到静态方法上,默认使用当前的类名.class的锁
    private void cal() {
        synchronized(ThreadCount.class){
            if (count > 1){
                count--;
                System.out.println(Thread.currentThread().getName() + " " + count);
            }
        }
    }

    public static void main(String[] args) {
        ThreadCount threadCount = new ThreadCount();
        new Thread(threadCount).start();
        new Thread(threadCount).start();
    }
}

4. 我们如果在使用 synchronized 需要注意 synchronized 锁嵌套的问题,避免死锁的问题发生,下面就是一个发生死锁的问题,线程1获取自定义的lock锁之后执行a()方法还需要获取this锁,线程2获取this锁之后执行b()方法还需要获取lock锁,当线程1和线程2在同时执行的时候,两个线程相互等待对方的锁释放一直在僵持那么就会造成死锁的问题:

package thread;

public class DeadLockThread implements Runnable{
    private int count = 100;
    private String lock = "lock";


    @Override
    public void run() {
        // 发生死锁问题
        while (true){
            count ++;
            if (count % 2 == 0){
                // 线程1获取lock之后还需要获取a方法this锁
                synchronized(lock){
                    a();
                }
            }else{
                // 线程2获取this锁还需要获取b方法lock锁
                synchronized (this){
                    b();
                }
            }
        }
    }

    public void b() {
        synchronized (lock){
            System.out.println(Thread.currentThread().getName() + " b方法");
        }
    }

    public synchronized void a() {
        System.out.println(Thread.currentThread().getName() + " a方法");
    }

    public static void main(String[] args) {
        DeadLockThread deadLockThread = new DeadLockThread();
        Thread thread1 = new Thread(deadLockThread);
        Thread thread2 = new Thread(deadLockThread);
        thread1.start();
        thread2.start();
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值