线程八锁问题

文章详细探讨了Java中的synchronized关键字在实例方法和静态方法中的应用,以及它如何影响线程同步。通过多个示例代码,展示了不同情况下synchronized锁的对象(实例或类对象),并分析了可能的执行顺序,包括线程间的等待和唤醒。这有助于理解Java并发编程中的锁机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

考察内容:synchronized 锁住的是哪个对象

本质上考察 synchronized 与 static synchronized 的区别:

  • synchronized 是实例锁,对类的当前实例进行加锁
  • static synchronized 是类锁,对类对象进行加锁

情况1

public class Test1 {
    public static void main(String[] args) {
        Number n1 = new Number();
        new Thread(() -> n1.a()).start();
        new Thread(() -> n1.b()).start();
    }
}

class Number {
    public synchronized void a() {
        log.debug("1");
    }

    public synchronized void b() {
        log.debug("2");
    }
}

两种可能

  • 12 
  • 21 

情况2

public class Test2 {
    public static void main(String[] args) {
        Number n1 = new Number();
        new Thread(() -> n1.a()).start();
        new Thread(() -> n1.b()).start();
    }
}

class Number{
    public synchronized void a(){
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.debug("1");
    }
    public synchronized void b() {
        log.debug("2");
    }
}

两种可能

  • 1s 后打印 12
  •  先打印2, 1s 后打印 1

情况3

public class Test3 {
    public static void main(String[] args) {
        Number n1 = new Number();
        new Thread(() -> n1.a()).start();
        new Thread(() -> n1.b()).start();
        new Thread(() -> n1.c()).start();
    }
}

class Number{
    public synchronized void a() {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.debug("1");
    }
    public synchronized void b() {
        log.debug("2");
    }
    public void c() {
        log.debug("3");
    }
}

三种可能

  • 先打印 3,1s 后打印 12
  • 先打印 23,1s 后打印 1
  • 先打印 32,1s 后打印 1

情况4

public class Test4 {
    public static void main(String[] args) {
        Number n1 = new Number();
        Number n2 = new Number();
        new Thread(() -> n1.a()).start();
        new Thread(() -> n2.b()).start();
    }
}

class Number{
    public synchronized void a() {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.debug("1");
    }
    public synchronized void b() {
        log.debug("2");
    }
}

一种可能,先打印 2,1s 后打印 1

情况5

public class Test5 {
    public static void main(String[] args) {
        Number n1 = new Number();
        new Thread(() -> n1.a()).start();
        new Thread(() -> n1.b()).start();
    }
}

class Number {
    public static synchronized void a() {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.debug("1");
    }

    public synchronized void b() {
        log.debug("2");
    }
}

一种可能,先打印 2,1s 后打印 1

情况6

public class Test6 {
    public static void main(String[] args) {
        Number n1 = new Number();
        new Thread(() -> n1.a()).start();
        new Thread(() -> n1.b()).start();
    }
}

class Number{
    public static synchronized void a() {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.debug("1");
    }
    public static synchronized void b() {
        log.debug("2");
    }
}

两种可能

  • 1s 后打印 12
  • 先打印 2,1s 后打印 1

情况7

public class Test7 {
    public static void main(String[] args) {
        Number n1 = new Number();
        Number n2 = new Number();
        new Thread(() -> n1.a()).start();
        new Thread(() -> n2.b()).start();
    }
}

class Number{
    public static synchronized void a() {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.debug("1");
    }
    public synchronized void b() {
        log.debug("2");
    }
}

一种可能,先打印 2,1s 后打印 1

情况8

public class Test8 {
    public static void main(String[] args) {
        Number n1 = new Number();
        Number n2 = new Number();
        new Thread(() -> n1.a()).start();
        new Thread(() -> n2.b()).start();
    }
}

class Number{
    public static synchronized void a() {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.debug("1");
    }
    public static synchronized void b() {
        log.debug("2");
    }
}

 两种可能

  • 1s 后打印 12
  • 先打印 2,1s 后打印 1
### Java 多线程中的八大 #### ReentrantLock (可重入) `ReentrantLock` 是一种常用的同步工具,允许同一线程多次获取同一个而不会发生死。下面是一个简单的 `ReentrantLock` 使用案例: ```java import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Counter { private int count = 0; private final Lock lock = new ReentrantLock(); public void increment() { lock.lock(); try { count++; } finally { lock.unlock(); } } public int getCount() { return count; } } ``` 这段代码展示了如何通过 `lock()` 和 `unlock()` 方法来保护共享资源[^1]。 #### ReadWriteLock (读写) 当多个线程需要访问同一数据结构时,可以使用读写提高性能。如果只有一个线程在修改数据,则其他只读取的线程不需要等待该线程完成操作即可继续执行。 ```java import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; class Cache<K, V> { private final Map<K, V> map = new HashMap<>(); private final ReadWriteLock rwl = new ReentrantReadWriteLock(); public V get(K key) { rwl.readLock().lock(); try { return map.get(key); } finally { rwl.readLock().unlock(); } } public void put(K key, V value) { rwl.writeLock().lock(); try { map.put(key, value); } finally { rwl.writeLock().unlock(); } } } ``` 此例子说明了如何利用读写优化并发场景下的缓存管理[^2]. #### StampedLock (乐观读/悲观写) 对于高并发环境下的复杂业务逻辑处理,`StampedLock` 提供了一种更灵活的选择。它支持三种模式:尝试定、乐观读以及写入定。 ```java import java.util.concurrent.locks.StampedLock; class Point { private double x, y; private final StampedLock sl = new StampedLock(); void move(double deltaX, double deltaY) { // an exclusively locked method long stamp = sl.writeLock(); try { x += deltaX; y += deltaY; } finally { sl.unlockWrite(stamp); } } double distanceFromOrigin() { // A read-only method long stamp = sl.tryOptimisticRead(); double currentX = x, currentY = y; if (!sl.validate(stamp)) { stamp = sl.readLock(); try { currentX = x; currentY = y; } finally { sl.unlockRead(stamp); } } return Math.sqrt(currentX * currentX + currentY * currentY); } } ``` 上述实例解释了如何运用不同类型的机制提升程序效率并减少竞争条件的影响[^3].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鲁蛋儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值