synchronized 锁的基本用法

本文详细探讨了Java中synchronized关键字的四种用法:1) 对Runnable实现类加锁,确保同一对象锁;2) 修饰实例方法,使用当前实例锁;3) 修饰静态方法,使用类名.class锁;4) 避免死锁:正确管理嵌套锁。通过实例演示和解释,帮助读者掌握并发编程的基石。
摘要由CSDN通过智能技术生成

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、付费专栏及课程。

余额充值