synchronized与lock的区别

举报
赵KK日常技术记录 发表于 2023/07/06 16:00:26 2023/07/06
【摘要】 synchronized与lock的区别 引言在多线程编程中,为了保证多个线程对共享资源的访问的正确性和一致性,需要使用线程加锁的机制。线程加锁可以避免多个线程同时访问共享资源而导致的数据竞争、不确定性和错误结果等问题。本文将介绍线程加锁的几种常见方式,并重点对比synchronized和lock两种常用的线程加锁机制的区别。 1. 线程加锁的方式 1.1 synchronized关键字s...

synchronized与lock的区别

引言

在多线程编程中,为了保证多个线程对共享资源的访问的正确性和一致性,需要使用线程加锁的机制。线程加锁可以避免多个线程同时访问共享资源而导致的数据竞争、不确定性和错误结果等问题。本文将介绍线程加锁的几种常见方式,并重点对比synchronized和lock两种常用的线程加锁机制的区别。

1. 线程加锁的方式

1.1 synchronized关键字

synchronized是Java中最基本、最常用的线程加锁机制。它可以修饰方法或代码块,用来实现对共享资源的访问控制。

1.1.1 synchronized修饰方法

当synchronized修饰一个方法时,表示该方法是一个同步方法。在调用该方法时,会自动获取该方法所属对象的锁,其他线程必须等待锁释放后才能访问该方法。

示例代码如下:

public class SynchronizedDemo {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }
}

1.1.2 synchronized修饰代码块

当synchronized修饰一个代码块时,需要指定一个对象作为锁。在执行到该代码块时,线程会尝试获取该对象的锁,其他线程必须等待锁释放后才能访问该代码块。

示例代码如下:

    private Object lock = new Object();
    private int count = 0;

    public void increment() {
        synchronized (lock) {
            count++;
        }
    }
}

1.2 lock接口

lock接口是Java.util.concurrent包中提供的一种更加灵活、可扩展的线程加锁机制。相比于synchronized关键字,lock接口提供了更多的功能和更细粒度的控制。

1.2.1 ReentrantLock类

ReentrantLock是lock接口的一个实现类,它实现了与synchronized相同的线程加锁功能,并且提供了更多的扩展功能。

示例代码如下:

    private Lock lock = new ReentrantLock();
    private int count = 0;

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }
}

1.2.2 ReadWriteLock接口

ReadWriteLock接口是Java中用于实现读写锁的接口,它提供了读锁和写锁的机制,以允许多个线程同时读取共享资源,但只允许一个线程进行写操作。

下面是一个简单的ReadWriteLock接口的实现示例:

public interface ReadWriteLock {
    Lock readLock();
    Lock writeLock();
}

在这个示例中,ReadWriteLock接口定义了两个方法:readLock()writeLock(),分别返回读锁和写锁的实例。

接下来,我们可以实现一个具体的ReadWriteLock接口,例如使用ReentrantReadWriteLock类:

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class MyReadWriteLock implements ReadWriteLock {
    private final ReentrantReadWriteLock lock;

    public MyReadWriteLock() {
        lock = new ReentrantReadWriteLock();
    }

    @Override    public Lock readLock() {
        return lock.readLock();
    }

    @Override    public Lock writeLock() {
        return lock.writeLock();
    }
}

在这个示例中,我们使用ReentrantReadWriteLock类来实现ReadWriteLock接口。在构造函数中,我们创建了一个ReentrantReadWriteLock实例。然后,我们通过实现readLock()和writeLock()方法,将对应的读锁和写锁返回。

使用这个自定义的ReadWriteLock实现,我们可以在多线程环境中进行读写锁的使用。例如:

    private static final ReadWriteLock rwLock = new MyReadWriteLock();
    private static final Lock readLock = rwLock.readLock();
    private static final Lock writeLock = rwLock.writeLock();

    public static void main(String[] args) {
        // 在读操作中使用读锁        new Thread(() -> {
            readLock.lock();
            try {
                // 执行读操作
            } finally {
                readLock.unlock();
            }
        }).start();

        // 在写操作中使用写锁
        new Thread(() -> {
            writeLock.lock();
            try {
                // 执行写操作            } finally {
                writeLock.unlock();
            }
        }).start();
    }
}

在这个示例中,我们创建了一个Main类,并在main()方法中创建了两个线程。一个线程使用读锁进行读操作,另一个线程使用写锁进行写操作。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。