详解线程同步和线程互斥,Java如何实现线程同步和互斥

简介: 详解线程同步和线程互斥,Java如何实现线程同步和互斥

1 Why?

首先第一个问题,为什么进行线程同步和线程互斥?

最开始我们的操作系统的作业的调度单位是进程,但是由于每个进程都单独占据一个资源,而且进程的形态转换非常的耗费系统资源。

为了系统的调度更加轻量级,能够更好的支持并发,因此引入了线程这个概念。

PS:进程和线程的关系:

  • 线程是进程的一个实体
  • 同一进程内的不同线程共享该进程的系统资源
    网络异常,图片无法展示
    |

  • 所以问题的答案来了,因为同一进程内的不同线程共享该进程的系统资源,这就导致了资源竞争的问题,为了能够解决这个问题,所以引入了线程互斥,就是为了能够在单位时间内只有一个线程共享该进程的系统资源。而进程同步就是让多个线程合理有序的访问该进程的系统资源。

2 What?

什么是线程同步?什么是线程互斥?

线程同步和线程互斥,类似于进程同步和进程互斥,在《操作系统》这本书中有另一个好听的名字:直接制约和间接制约

直接制约(同步关系):

某些应用程序,为了完成某个任务而建立了两个或多个进程(源于进程间的合作)。

网络异常,图片无法展示
|


间接制约(互斥关系):

多个程序并发执行时,由于共享系统资源(如CUP、I/O设备等)而导致这些并发执行的程序之间形成相互的制约

的关系。

网络异常,图片无法展示
|


因此,我们知道了线程同步和线程互斥的关系:

  1. 互斥是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性,访问是无序的。
  2. 同步是指在互斥的基础上,通过其它机制实现访问者对资源的有序访问。
  3. 同步其实已经实现了互斥,所以同步是一种更为复杂的互斥。
  4. 互斥是一种特殊的同步。

3 How?

Java如何实现线程同步和线程互斥?

先说简单的,Java实现线程互斥:

无线程互斥的情况

/**
 * @desc: 没有进行互斥的情况
 * @author: YanMingXin
 * @create: 2021/12/19-18:02
 **/
public class Method0 {
    private int value = 10;
    private void reduce() {
        try {
            while (value == 0) {
                System.out.println("stop...");
                return;
            }
            System.out.println(Thread.currentThread().getName() + ":" + value);
            value--;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private void make() {
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(3, 5, 3, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
        for (int i = 0; i < 20; i++) {
            poolExecutor.execute(() -> {
                reduce();
            });
        }
    }
    public static void main(String[] args) {
        Method0 methodA = new Method0();
        methodA.make();
    }
}
复制代码

方式一:互斥锁synchronized

/**
 * @desc: 互斥方式一
 * @author: YanMingXin
 * @create: 2021/12/19-17:48
 **/
public class MethodA {
    private int value = 10;
    private synchronized void reduce() {
        try {
            while (value == 0) {
                System.out.println("stop...");
                return;
            }
            System.out.println(Thread.currentThread().getName() + ":" + value);
            value--;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private void make() {
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(3, 5, 3, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
        for (int i = 0; i < 20; i++) {
            poolExecutor.execute(() -> {
                reduce();
            });
        }
    }
    public static void main(String[] args) {
        MethodA methodA = new MethodA();
        methodA.make();
    }
}
复制代码

方式二:可重入互斥锁ReentrantLock

/**
 * @desc: 互斥方式二
 * @author: YanMingXin
 * @create: 2021/12/19-17:50
 **/
public class MethodB {
    private int value = 10;
    private ReentrantLock lock=new ReentrantLock();
    private void reduce(){
        lock.lock();
        try {
            while (value == 0) {
                System.out.println("stop...");
                return;
            }
            System.out.println(Thread.currentThread().getName() + ":" + value);
            value--;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    private void make() {
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(3, 5, 3, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
        for (int i = 0; i < 20; i++) {
            poolExecutor.execute(() -> {
                reduce();
            });
        }
    }
    public static void main(String[] args) {
        MethodB methodA = new MethodB();
        methodA.make();
    }
}
复制代码

然后,Java实现线程同步:

无线程同步的情况

/**
 * @desc: 无线程同步状态
 * @author: YanMingXin
 * @create: 2021/12/19-17:47
 **/
public class Method0 {
    private int value = 0;
    private static List list = new ArrayList<String>();
    static {
        list = Arrays.asList("1-Insert", "2-Delete", "3-Update", "4-Select");
    }
    private void reduce() {
        try {
            System.out.println(list.get(value));
            value++;
            while (value > 3) {
                System.out.println("stop...");
                return;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private void make() {
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
                4,
                4,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>());
        for (int i = 0; i < 4; i++) {
            poolExecutor.execute(() -> {
                reduce();
            });
        }
        poolExecutor.shutdown();
    }
    public static void main(String[] args) {
        Method0 methodA = new Method0();
        methodA.make();
    }
}
复制代码

方式一:synchronized进行线程同步

/**
 * @desc: 线程同步方式一
 * @author: YanMingXin
 * @create: 2021/12/19-17:47
 **/
public class MethodA {
    private int value = 0;
    private static List list = new ArrayList<String>();
    static {
        list = Arrays.asList("1-Insert", "2-Delete", "3-Update", "4-Select");
    }
    private synchronized void reduce() {
        try {
            System.out.println(list.get(value));
            value++;
            while (value > 3) {
                System.out.println("stop...");
                return;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private void make() {
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
                4,
                4,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>());
        for (int i = 0; i < 4; i++) {
            poolExecutor.execute(() -> {
                reduce();
            });
        }
        poolExecutor.shutdown();
    }
    public static void main(String[] args) {
        MethodA methodA = new MethodA();
        methodA.make();
    }
}
复制代码

方式二:ReentrantLock进行线程同步

/**
 * @desc: 线程同步方式二
 * @author: YanMingXin
 * @create: 2021/12/19-17:47
 **/
public class MethodA {
    private int value = 0;
    private ReentrantLock lock = new ReentrantLock();
    private static List list = new ArrayList<String>();
    static {
        list = Arrays.asList("1-Insert", "2-Delete", "3-Update", "4-Select");
    }
    private void reduce() {
        lock.lock();
        try {
            System.out.println(list.get(value));
            value++;
            while (value > 3) {
                System.out.println("stop...");
                return;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    private void make() {
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
                4,
                4,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>());
        for (int i = 0; i < 4; i++) {
            poolExecutor.execute(() -> {
                reduce();
            });
        }
        poolExecutor.shutdown();
    }
    public static void main(String[] args) {
        MethodA methodA = new MethodA();
        methodA.make();
    }
}
复制代码

方式三:synchronized代码块

/**
 * @desc: 线程同步方式三
 * @author: YanMingXin
 * @create: 2021/12/19-17:47
 **/
public class MethodA {
    private int value = 0;
    private static List list = new ArrayList<String>();
    static {
        list = Arrays.asList("1-Insert", "2-Delete", "3-Update", "4-Select");
    }
    private void reduce() {
        synchronized (this) {
            try {
                System.out.println(list.get(value));
                value++;
                while (value > 3) {
                    System.out.println("stop...");
                    return;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    private void make() {
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
                4,
                4,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>());
        for (int i = 0; i < 4; i++) {
            poolExecutor.execute(() -> {
                reduce();
            });
        }
        poolExecutor.shutdown();
    }
    public static void main(String[] args) {
        MethodA methodA = new MethodA();
        methodA.make();
    }
}
复制代码

参考文章:

www.cnblogs.com/baizhanshi/…


相关文章
|
22小时前
|
Java 数据处理 调度
Java多线程编程入门指南
Java多线程编程入门指南
|
1天前
|
监控 安全 算法
如何有效地处理Java中的多线程
如何有效地处理Java中的多线程
|
2天前
|
Java 调度
Java多线程编程与并发控制策略
Java多线程编程与并发控制策略
|
1天前
|
安全 Java 开发者
Java并发编程中的线程安全策略
在现代软件开发中,Java语言的并发编程特性使得多线程应用成为可能。然而,随着线程数量的增加,如何确保数据的一致性和系统的稳定性成为开发者面临的挑战。本文将探讨Java并发编程中实现线程安全的几种策略,包括同步机制、volatile关键字的使用、以及java.util.concurrent包提供的工具类,旨在为Java开发者提供一系列实用的方法来应对并发问题。
8 0
|
1天前
|
监控 Java UED
Java并发编程:深入理解线程池的设计与应用
本文旨在通过数据导向和科学严谨的方式,深入探讨Java并发编程中的关键组件——线程池。文章首先概述了线程池的基本概念与重要性,随后详细解读了线程池的核心参数及其对性能的影响,并通过实验数据支持分析结果。此外,文中还将介绍如何根据不同的应用场景选择或设计合适的线程池,以及如何避免常见的并发问题。最后,通过案例研究,展示线程池在实际应用中的优化效果,为开发人员提供实践指导。
7 0
|
2天前
|
存储 缓存 Java
Java并发编程之线程池的使用
Java并发编程之线程池的使用
|
2天前
|
安全 Java 调度
精通Java中的线程同步与互斥
精通Java中的线程同步与互斥
|
1月前
|
安全 Java
深入理解Java并发编程:线程安全与性能优化
【2月更文挑战第22天】在Java并发编程中,线程安全和性能优化是两个重要的主题。本文将深入探讨这两个主题,包括线程安全的基本概念,如何实现线程安全,以及如何在保证线程安全的同时进行性能优化。
27 0
|
30天前
|
存储 安全 Java
深入理解Java并发编程:线程安全与锁机制
【5月更文挑战第31天】在Java并发编程中,线程安全和锁机制是两个核心概念。本文将深入探讨这两个概念,包括它们的定义、实现方式以及在实际开发中的应用。通过对线程安全和锁机制的深入理解,可以帮助我们更好地解决并发编程中的问题,提高程序的性能和稳定性。
|
1月前
|
安全 Java 容器
Java一分钟之-并发编程:线程安全的集合类
【5月更文挑战第19天】Java提供线程安全集合类以解决并发环境中的数据一致性问题。例如,Vector是线程安全但效率低;可以使用Collections.synchronizedXxx将ArrayList或HashMap同步;ConcurrentHashMap是高效线程安全的映射;CopyOnWriteArrayList和CopyOnWriteArraySet适合读多写少场景;LinkedBlockingQueue是生产者-消费者模型中的线程安全队列。注意,过度同步可能影响性能,应尽量减少共享状态并利用并发工具类。
34 2