多线程常见问题汇总

本文深入探讨了Java并发编程中的锁机制,包括synchronized关键字的使用,volatile字段的可见性与原子性,以及Atomic类的原子操作。讲解了线程异常时锁的释放,死锁的示例,细粒度锁与性能,wait方法的配合使用,以及避免字符串常量作为锁对象导致的死锁问题。此外,还提到了方法同步的细节和静态方法同步的区别。

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

1.A线程正在执行一个对象中的同步方法,B线程可以执行同一个对象的非同步方法,但是不能执行同对象的其他同步方法

2.线程抛出异常会释放锁--可catch异常回滚事务

3.volatile 修饰字段,一个线程修改该字段,会通知其他线程重新读取该字段 ,volatile保证了可见性,但是没有保证原子性,synchronized 既可以保证可见性,也能保证原子性;volatile比synchronized性能好,能用volatile就用volatile

4.Atomicxxxxxx类中的方法是原子性的,可见性的,但是多个方法间一起使用,方法间的间隙会产生非原子操作

5.synchronized锁住的是堆内存里的对象,而非栈上面的引用,当发生异常的时候,会释放锁,其他线程可执行;当变量指向一块新的对象时,其他线程可使用新的对象锁,见下面Demo

import java.util.concurrent.TimeUnit;

public class T5 {

    private Object o = new Object();


    public void m(){

        synchronized (o){
            while(true){
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName());
            }
        }

    }

    public static void main(String[] args) {
        T5 t = new T5();

        new Thread(t::m).start();

        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


        t.o = new Object();

        new Thread(t::m).start();
    }
}

6.不要以字符串常量作为锁定对象,不然容易出现死锁,如果锁定的是字符串,这个字符串可能在常量池已经出现过并被其他线程锁住;这种情况使用起来就不知不觉的出现死锁;

7.成员方法上添加synchronized 等同于方法内添加synchronized(this){} ,锁住对象本身,而非一段代码;静态方法上添加synchronized等同于在静态方法内synchronized(xxx.class){},静态方法上加synchronized和成员方法上加synchronized两个方法不互斥

8.写加锁,读不加锁,容易出现脏读

9.一个线程执行一个同步方法时,方法中调用另一个同步方法,是可以的,这个线程申请了这个对象锁,当访问另一个同步方法时,再申请一次该对象锁,synchronized是可重入锁,访问结束,锁也会释放两次,同样子类的同步方法可以调用父类的同步方法

10.死锁Demo

public class DeadLock {

    private Object o1 = new Object();

    private Object o2 = new Object();

    public  void f1() throws InterruptedException {
        synchronized(o1){
            System.out.println(Thread.currentThread().getName()+"获得o1锁");
            Thread.sleep(2000);
            synchronized(o2){
                System.out.println(Thread.currentThread().getName()+"获得o2锁");

            }
        }
    }

    public  void f2() throws InterruptedException {
        synchronized(o2){
            System.out.println(Thread.currentThread().getName()+"获得o2锁");
            Thread.sleep(2000);
            synchronized(o1){
                System.out.println(Thread.currentThread().getName()+"获得o1锁");

            }
        }
    }

    public static void main(String[] args) throws Exception{
        DeadLock deadLock = new DeadLock();


        new Thread(() -> {
            try {
                deadLock.f1();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        new Thread(() -> {
            try {
                deadLock.f2();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }


}

11.细粒度的锁要比粗粒度的锁性能提高不少

12.wait方法百分99之情况都和while一起使用

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值