前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java线程锁Synchronized

Java线程锁Synchronized

作者头像
smallmayi
发布2022-05-12 11:19:02
2420
发布2022-05-12 11:19:02
举报
文章被收录于专栏:small专栏
什么是线程锁?

在并发编程中,经常遇到多个线程访问同一个 共享资源 ,这时候作为开发者必须考虑如何维护数据一致性,在java中synchronized关键字被常用于维护数据一致性。synchronized机制是给共享资源上锁,只有拿到锁的线程才可以访问共享资源,这样就可以强制使得对共享资源的访问都是顺序的。

引入多线程后,为解决线程安全问题而引入锁的概念,java中常用的锁有synchronized和lock两种。

java中的锁

一般在java中所说的锁就是指的内置锁,每个java对象都可以作为一个实现同步的锁,虽然说在java中一切皆对象, 但是锁必须是引用类型的,基本数据类型则不可以 。每一个引用类型的对象都可以隐式的扮演一个用于同步的锁的角色,执行线程进入synchronized块之前会自动获得锁,无论是通过正常语句退出还是执行过程中抛出了异常,线程都会在放弃对synchronized块的控制时自动释放锁。 获得锁的唯一途径就是进入这个内部锁保护的同步块或方法 。

通过synchronized的关键字来实现线程同步锁

synchronized 锁住的是对象

Synchronized 三种应用方式:

1.作用于实例方法(普通方法),当前实例加锁,进入同步代码前要获得当前实例的锁; 例如:

代码语言:javascript
复制
public class SyncTest implements Runnable{
//共享资源变量
static int count = 0;

    @Override
    public synchronized void run() {
        increaseCount();
    }

    private synchronized  void increaseCount() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + count++);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        SyncTest syncTest1 = new SyncTest();
//        SyncTest syncTest2 = new SyncTest();
        Thread thread1 = new Thread(syncTest1, "thread1");
        Thread thread2 = new Thread(syncTest1, "thread2");
        thread1.start();
        thread2.start();
    }
    
    /**
     * 执行结果
     * thread1:0
     * thread1:1
     * thread1:2
     * thread1:3
     * thread1:4
     * thread2:5
     * thread2:6
     * thread2:7
     * thread2:8
     * thread2:9
     */
}

上面是创建1个对象和两个线程,可以看到Thread1和Thread2 按顺序执行 当创建两个不同的对象时,两个线程同步执行,所以说锁住的是对象。如下:

代码语言:javascript
复制
public class SyncTest implements Runnable{
//共享资源变量
static int count = 0;

    @Override
    public synchronized void run() {
        increaseCount();
    }

    private synchronized  void increaseCount() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + count++);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        SyncTest syncTest1 = new SyncTest();
        SyncTest syncTest2 = new SyncTest();
        Thread thread1 = new Thread(syncTest1, "thread1");
        Thread thread2 = new Thread(syncTest2, "thread2");
        thread1.start();
        thread2.start();
    }

    /**
     * 执行结果
     thread2:1
     thread1:0
     thread1:2
     thread2:3
     thread2:4
     thread1:4
     thread1:5
     thread2:5
     thread2:6
     thread1:7
     */
}

2.作用于静态方法,当前类加锁,进去同步代码前要获得当前类对象的锁;

代码语言:javascript
复制
public class SyncTest implements Runnable {
    //共享资源变量
    static int count = 0;

    @Override
    public synchronized void run() {
        increaseCount();
    }

    private sys static void increaseCount() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + count++);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        SyncTest syncTest1 = new SyncTest();
        SyncTest syncTest2 = new SyncTest();
        Thread thread1 = new Thread(syncTest1, "thread1");
        Thread thread2 = new Thread(syncTest2, "thread2");
        thread1.start();
        thread2.start();
    }

    /**
     * 执行结果
     thread1:0
     thread1:1
     thread1:2
     thread1:3
     thread1:4
     thread2:5
     thread2:6
     thread2:7
     thread2:8
     thread2:9
     */
}

synchronized 作用于静态方法时,相当于给该类加锁,如上创建两个对象分开两个线程依旧按顺序执行。

3.作用于代码块,这需要指定加锁的对象,对所给的指定对象加锁,进入同步代码前要获得指定对象的锁。

代码语言:javascript
复制
public class SyncTest implements Runnable {
    //共享资源变量
    static int count = 0;
    private byte[] mBytes = new byte[0];

    @Override
    public synchronized void run() {
        increaseCount();
    }

    private void increaseCount() {
        //假设省略了其他操作的代码。
        //……………………
        synchronized (this) {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + ":" + count++);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        SyncTest syncTest1 = new SyncTest();
        SyncTest syncTest2 = new SyncTest();
        Thread thread1 = new Thread(syncTest1, "thread1");
        Thread thread2 = new Thread(syncTest1, "thread2");
        thread1.start();
        thread2.start();
    }

    /**
     * 执行结果
     thread1:0
     thread1:1
     thread1:2
     thread1:3
     thread1:4
     thread2:5
     thread2:6
     thread2:7
     thread2:8
     thread2:9
     */

当只需要部分代码同步时,synchronized 作用于代码块,传入参数为对象,效果和作用于普通方法一致,锁住的是对象。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-10-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是线程锁?
  • java中的锁
  • 通过synchronized的关键字来实现线程同步锁
    • Synchronized 三种应用方式:
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档