Java学习

java中的实例锁(Synchronized)和类锁(Stati

2019-02-26  本文已影响10人  唐T唐X

这篇文章我们简单了解下java中实例锁和类锁。

在这里先给个福利,恶补下锁的作用:对于并发工作,你需要某种方式来防止两个任务访问相同的资源(其实就是共享资源竞争)。 防止这种冲突的方法就是当资源被一个任务使用时,在其上加锁。第一个访问某项资源的任务必须锁定这项资源,使其他任务在其被解锁之前,就无法访问它了,而在其被解锁之时,另一个任务就可以锁定并使用它了。

下面进入正题:

实例锁:对一个类的一个实例对象(对象A)进行加锁,防止其他线程同时访问对象A的synchronized块,但是对不同的此类的实例对象不做控制。实例锁使用Synchronized关键字修饰。

类锁:对一个类的所有实例对象进行加锁,限制多线程中该类的所有实例同时访问该类的synchronized块。类锁使用Static Synchronized关键字修饰。

文字比较生涩,我们看看代码:

实例锁

package com.xingshulin;

public class ObjectSyncTest implements Runnable {

    int salary = 0;

    public void run(){
        addSalary();
    }

    public synchronized void addSalary() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        salary += 1;
        System.out.println(salary);
    }

    public static void main(String[] args) {
        ObjectSyncTest st = new ObjectSyncTest();
        for (int i = 0; i < 10; i++) {
            new Thread(st).start();
        }
    }
}

返回结果:

1
2
3
4
5
6
7
8
9
10

Process finished with exit code 0

代码很简单,我们可以看到addSalary方法是使用synchronized修饰的,所以它是实例锁。在main函数中我们使用了一个对象st,并生成了10个线程对st对象中的变量salary进行+1操作,可以看到最终结果确实是同步的。
有些童鞋会问了,那我要是把synchronized关键字去掉呢?其实这就是线程安全的问题了,在这里不多说,但是我们可以看下去掉后的返回值:

5
7
9
9
6
6
9
8
4
7

Process finished with exit code 0

很明显不对了是吧,再多试几遍,虽然每次得到的结果都不同,但是很明显都是不对的。这就是因为没有加同步锁,在程序运行中产生了线程冲突。

类锁

package com.xingshulin;

public class ClassSyncTest implements Runnable {

    public static int salary = 0;

    public void run(){
        addSalary();
    }

    public static synchronized void addSalary() {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        salary += 1;
        System.out.println(salary);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            ClassSyncTest st = new ClassSyncTest();
            new Thread(st).start();
        }
    }
}

返回结果:

1
2
3
4
5
6
7
8
9
10

Process finished with exit code 0

结合实例锁的代码来看,对比很明显了。代码中addSalary方法是使用static synchronized关键字修饰的,所以它是类锁。而在main函数中使用了10个不同的对象st,每个对象都对变量salary进行+1操作,可以看到最终结果也是同步的。
为了证明确实类锁管用,我们把static关键字删掉(变成了实例锁),这样再跑下程序:

3
3
3
4
8
8
9
5
6
7

Process finished with exit code 0

很明显,线程又冲突了,所以也正好证明了实例锁只能管自己的一个实例,对于类中的所有实例是无法做到同步的。

上一篇 下一篇

猜你喜欢

热点阅读