Java内置锁简单用法

概念及解释

Java的内置锁:每个Java对象都可以用做一个实现同步的锁,这些锁成为内置锁。线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁。获得内置锁的唯一途径就是进入这个锁的保护的同步代码块或方法。

重入:某个线程请求一个由其他线程持有的锁时,发出请求的线程会阻塞。如果线程试图获取一个已经由它自己持有的锁,那么他发出的请求就会成功。

1.Java内置锁是一个互斥锁,这就是意味着最多只有一个线程能够获得该锁,当线程A尝试去获得线程B持有的内置锁时,线程A必须等待或者阻塞,知道线程B释放这个锁,如果B线程不释放这个锁,那么A线程将永远等待下去。

2.Java内置锁的区分:对象锁是用于对象实例方法,或者一个对象实例上的,类锁是用于类的静态方法或者一个类的class对象上的。一个对象对应一个对象锁一个类只有一个类锁。类锁只是一个概念上的东西,并不是真实存在的,它只是用来帮助我们理解锁定实例方法和静态方法的区别的

用法

public class SynchronizedTest {

    private static int value = 0;

    private final Object object = new Object();


    /**
     * 线程不安全的
     *
     * @return
     * @throws Exception
     */
    public int getValue() throws Exception {
        value++;
        Thread.sleep(100);
        return value;
    }

    /**
     * 线程安全的
     * 非静态方法加锁
     * 方法锁(对象锁的一种)
     * @return
     * @throws InterruptedException
     */
    public synchronized int getValue1() throws InterruptedException {
        value++;
        Thread.sleep(100);
        return value;
    }

    /**
     * 线程安全的
     * 静态方法加锁
     * 类锁
     *
     * @return
     * @throws InterruptedException
     */
    public static synchronized int getValue2() throws InterruptedException {
        value++;
        Thread.sleep(100);
        return value;
    }

    /**
     * 线程安全的
     * 对象锁
     * @return
     * @throws InterruptedException
     */
    public int getValue3() throws InterruptedException {
        synchronized (object) {
            value++;
            Thread.sleep(100);
            return value;
        }
    }

    /**
     * 线程安全的
     * 类锁
     * @return
     * @throws InterruptedException
     */
    public int getValue4() throws InterruptedException {
        synchronized (Object.class) {
            value++;
            Thread.sleep(100);
            return value;
        }
    }

    public static void main(String[] args) {
        final SynchronizedTest synchronizedTest = new SynchronizedTest();
        //创建了一个最大容量为5的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(5);

        for (int i = 1; i < 10; i++) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println(synchronizedTest.getValue());//调用非安全的方法
                        //System.out.println(synchronizedTest.getValue1());//调用加了方法锁的方法
                        //System.out.println(synchronizedTest.getValue2());//调用加了类锁的方法
                        //System.out.println(synchronizedTest.getValue3());//调用对象锁代码块的方法
                        //System.out.println(synchronizedTest.getValue4());//调用类锁代码块的方法
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        executorService.shutdown();
    }

}

测试结果

非线程安全的方法getValue运行结果

在这里插入图片描述
其他线程安全的方法运行结果
在这里插入图片描述

注意事项

1.一个类的对象锁和另一个类的对象锁是没有关联的,当一个线程获得A类的对象锁时,它同时也可以获得B类的对象锁。

2.一个类中带对象锁的方法和不带锁的方法,可以异步执行,不干扰,不需要等待。

3.一个类中,如果set()方法加了对象锁,get()方法不加对象锁,容易发生数据脏读。可以用类锁或者set、get都加对象锁,解决。

4.同一个类中,多个锁方法相互调用,线程安全。

5.父子类中,锁方法相互调用,线程安全。

6.锁重入,在继承关系中适用。

7.锁方法发生异常时,会自动释放锁。程序继续执行,如果没有响应的处理,会发生业务逻辑的漏洞或者混乱。多见批处理、消息队列等。

8.类中的object成员变量加锁,为任意对象锁。

9.String常量值加锁,容易发生死锁。

10.如果你在一个对象锁方法中,对这个锁对象的引用做了修改,则表示释放了锁对象。如重新new object(),赋值给这个锁对象。但是锁对象的属性或值发生改变,并不发生锁的释放。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值