前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java并发编程:多线程同步和互斥有几种实现方法

Java并发编程:多线程同步和互斥有几种实现方法

作者头像
用户1289394
发布2023-08-22 16:53:46
2680
发布2023-08-22 16:53:46
举报
文章被收录于专栏:Java学习网

在Java并发编程中,多线程同步和互斥是非常重要的概念。为了保证程序的正确性和性能,我们需要使用多种方式来实现多线程之间的同步和互斥。

一、synchronized关键字

synchronized关键字是Java中最常用的实现多线程同步和互斥的方法之一。通过给某个对象或方法添加synchronized修饰符可以保证多个线程之间的互斥性,即当一个线程获得某个对象的锁时,其他线程必须等待该线程释放该锁才能够执行对应代码块。此外,synchronized还具有可见性,即当一个线程释放锁时,会将锁变量的值刷新到主存储器中,从而使其它线程可以感知到锁状态的变化。

示例如下:

代码语言:javascript
复制
public class Test {
    private static int count = 0;

    public static synchronized void add() {
        count++;
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                add();
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                add();
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(count); //输出20000
    }
}

在上述示例中,我们定义了一个静态变量count,并通过synchronized关键字修饰add()方法实现对count的访问同步和互斥。最终输出结果为20000。

二、ReentrantLock类

ReentrantLock是Java.util.concurrent包中提供的另一种实现互斥性的方式。与synchronized相比,ReentrantLock具有更加灵活的控制锁的机制,可以支持选择公平锁或者非公平锁等高级特性。

代码语言:javascript
复制
public class Test {
    private static int count = 0;
    private final static Lock lock = new ReentrantLock(true);

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

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                add();
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                add();
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(count); //输出20000
    }
}

上述示例中,在add()方法中,我们使用ReentrantLock类来实现线程之间的互斥访问。并且通过lock()和unlock()方法手动获取和释放该对象的锁status。最终输出结果与前一个示例代码一致。

三、AtomicInteger类

对于只需要进行基本计数的场景,可以使用Java中的原子类,例如AtomicInteger。由于其底层实现是基于CAS(Compare And Swap)原语实现的,所以不需要显式地加锁,也可以保证线程之间的互斥性和可见性。

代码语言:javascript
复制
public class Test {
    private static AtomicInteger count = new AtomicInteger(0);

    public static void add() {
        count.getAndIncrement();
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                add();
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                add();
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(count); //输出20000
    }
}

上述示例代码中,我们定义了一个AtomicInteger对象来实现对count的自增操作,输出结果与前两个示例相同。

总之,在Java并发编程中,为了保证多线程之间的正确性和性能,我们需要使用多种方式来实现多线程同步和互斥,常用的包括synchronized关键字、ReentrantLock类和原子类等。我们应该根据具体应用场景选择合适的方法来确保程序执行的正确性和高效性。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-07-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java学习网 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档