- 浏览: 91543 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (148)
- 全文检索 (1)
- java (29)
- xml (2)
- json (2)
- redis springmvc (1)
- Redis (5)
- 开发常识 (1)
- tomcat (2)
- 单元测试Junit (2)
- 设计模式 (2)
- spring (10)
- jvm (2)
- eclipse (4)
- echart (1)
- mybatis (1)
- mysql (3)
- web (1)
- js (2)
- PL/SQL (2)
- 其他 (1)
- 人生 (1)
- 安全 (2)
- jsp (2)
- 硬件电脑 (1)
- linux (3)
- git (10)
- oracle (8)
- ant (1)
- maven (2)
- 正则表达式 (2)
- chrome (1)
- 面试 (6)
- 多线程 (19)
- bug (11)
- java工具类 (3)
- 算法 (1)
- bug,git (1)
- shell (2)
- springmvc (2)
- Java8 (1)
- 消息队列-rocketmq (1)
- es (1)
- dubbo (0)
- spring cloud (0)
- hashmap (0)
- springboot (1)
- velocity (0)
线程的同步机制
(一)如果并发执行的多个线程间需要共享资源或交换数据,则这一组线程称为交互线程。
(二)交互线程并发执行时相互之间会干扰或影响其他线程的执行结果,因此交互线程之间需要有同步机制。
(三)交互线程之间存在两种关系:竞争关系和协作关系。
(四)对于竞争关系的交互线程间需要采用线程互斥方式解决共享资源冲突问题;
(五)对于协作关系的交互线程间需要采用线程同步方式解决线程间通信及因执行速度不同而引起的不同步问题。
(六)线程的同步机制包括线程互斥和线程同步,线程互斥是线程同步的特殊情况。
交互线程
无关线程与交互线程
并发线程之间可能是无关的,也可能是交互的。
无关的并发线程是指它们分别在不同的变量集合上操作。一个线程的执行与其他并发线程的进展无关,即一个并发线程不会改变另一个并发线程的变量值。
交互的并发线程是指他们共享某些变量,一个线程的执行可能影响其他线程的执行结果,交互的并发线程之间具有制约关系。因此,线程的交互必须是有控制的,否则会出现不正确的结果。
并发执行的交互线程间存在与时间有关的错误
无关线程间并发执行时不会产生与时间有关的错误。例如,奇数线程与偶数线程是两个并发执行的无关线程。程序每次运行,它们之间的执行次序可能会因线程调度而不同,但不会影响对方的结果值,奇数线程中绝不会输出偶数。
交互的并发线程执行时,由于它们在不同时刻对同一个共享变量进行操作,线程之间相互影响、相互干扰,因此计算结果往往取决于这一组并发线程的相对速度,各种与时间有关的错误就可能出现。
例如:将对银行账户的存款、取款操作分别设计成线程,存款线程与取款线程能够对同一个账户数据进行操作,此时该账户称为共享变量,并发执行的多个存款、取款线程间可能会产生与时间有关的错误。
package com.jbx.thread.account; public class Account { //账户类 private String name; //储户姓名 private double balance; //账户余额 public Account(String name) { this.name = name; this.balance = 0; } public String getName() { //返回账户名 return name; } public double getBalance() { //查看账户余额 return balance; } public void put(double value) { //存款操作,参数为存入金额 if(value>0) this.balance += value; //存款操作使余额值增加//存款操作,参数为取款金额,返回实际取到金额 } public double get(double value){ //取款操作,参数为取款金额,返回实际取到金额 if(value>0){ if(value<=this.balance) this.balance -= value; //取款操作使余额值减少 else{ value= this.balance; //取走全部余额 this.balance = 0; } return value; //返回实际取款额 } return 0; } } class Save extends Thread{ //存款线程类 private Account account; //账户 private double value; //存款金额 public Save(Account al ,double value){ this.account = al; this.value = value; } public void run(){ double howmatch = this.account.getBalance();//查看账户余额 this.account.put(this.value); try { sleep(1); //花费实际,线程执行被打断 } catch (InterruptedException e) {} System.out.println(this.account.getName()+"账户:现有"+howmatch+",存入"+this.value+",余额"+this.account.getBalance()); } } class Fetch extends Thread{ private Account account; // private double value; // public Fetch(Account al ,double value){ this.account = al; this.value = value; } public void run(){ double howmatch = this.account.getBalance();//查看账户余额 this.account.put(this.value); try { sleep(1); //花费实际,线程执行被打断 } catch (InterruptedException e) {} System.out.println(this.account.getName()+"账户:现有"+howmatch+",取走"+this.account.get(this.value)+",余额"+this.account.getBalance()); } public static void main(String[] args) { Account wang = new Account("wang"); (new Save(wang,100)).start(); //存100 (new Save(wang,100)).start(); //存200 (new Fetch(wang,100)).start(); //取300 } }
运行结果:
wang账户:现有0.0,存入100.0,余额300.0
wang账户:现有100.0,存入100.0,余额300.0
wang账户:现有200.0,取走100.0,余额200.0
解析:
main方法中对wang创建并启动了2个存款线程和1个取款线程。3个线程对象能够对同一个账户对象中数据进行操作,但每次运行的结果不确定,出现与时间有关的并发执行问题。
程序设计运行结果的讨论如下:
(1)运行结果不唯一,取决于线程调度
如果存/取款操作花费时间较短,线程执行没有被打断,即线程体中没有sleep延时,则程序运行结果不确定。取款线程实际取到的金额可能是0、100、200或300,取决于2个存款线程是否执行完成,与线程调度有关。一种可能的运行结果如下:
wang账户:现有0.0,存入100.0,余额100.0
wang账户:现有100.0,取走100.0,余额 0.0
wang账户:现有100.0,存入200.0,余额200.0
(2)线程执行被打断时出现错误
执行一个存/取款线程对象的run()方法,首先查看指定账户的现有金额,再进行存/取款操作,如果执行时间较长线程将会被打断。程序中用sleep(1)模拟线程执行被打断的情况,运行结果如下:
wang账户:现有0.0,存入100.0,余额100.0
wang账户:现有100.0,取走100.0,余额 0.0 //有错,三者数据不符
wang账户:现有100.0,存入200.0,余额200.0 //有错,三者数据不符
3个线程启动后都进入运行态,每个线程在查看了账户余额后被打断,尽管sleep时间只有1ms,很短暂,但足以改变线程状态,线程被迫让出处理器,暂停运行。系统调度其他线程运行,其他并发执行线程修改了同一账户的共享数据,导致线程再次运行时,该账户余额已不是其先前查看的金额,因而运行结果中查看金额、存/取金额和剩余金额三者数据不相符,这严重破坏了数据的完整性和一致性。
错误产生的原因是:多个线程交替访问同一个共享变量,干扰其他线程的执行结果。
避免出现错误的办法是:多个线程串行地、互斥地访问共享变量。
如果有两个线程同时分别对两个不同账户对象进行操作,则线程执行将不受干扰。例如:
(new Save(wang,200)).start();
(new Save(new Account("Li"),100)).start();
发表评论
-
ThreadPoolExecutor线程池参数详解
2019-01-09 00:06 478参考:https://www.cnblogs.com/wayt ... -
解决线程同步问题的思路
2018-07-31 16:35 418线程同步机制 操作系统中实现线程同步有一种工 ... -
发送线程与接收线程 速率一致
2018-08-07 09:17 384package com.jbx.xiezuo; /* ... -
线程间的协作关系与线程同步
2018-07-30 16:21 5291.线程间的协作关系 当一个进程中的多个线程为完成同 ... -
带互斥锁的并发线程执行流程
2018-07-30 12:38 449... -
线程间的竞争关系与线程互斥
2018-07-30 11:19 672线程间的竞争关系与线 ... -
3个线程,A,B,C,这三个线程分别只能打印 “a”,“b”,“c”,怎么让这三个线程依次打印“abc"
2018-07-17 11:19 351package com.jbx.thread; /* ... -
定时器与图形动画设计
2018-07-17 11:15 0动画(animation) 都是利用人眼的视 ... -
线程分类
2018-07-17 09:10 327线程分类: 线程可分为用户线程(user thread) ... -
线程优先级
2018-07-17 09:08 360Java提供10个等级的线程优先级,分别用1~10表示,优先级 ... -
设计滚动字演示线程状态及改变方法
2018-07-16 16:17 305本例演示线程对象的生 ... -
线程对象的生命周期
2018-07-16 11:28 362线程对象的生命周期 1.Thread.State类声明的线程状 ... -
声明实现Runnable接口的奇数/偶数序列线程
2018-07-11 14:02 428package com.jbx.thread; ... -
声明继承Thread类的奇数/偶数序列线程
2018-07-10 23:58 420package com.jbx.com; /** ... -
Java的线程对象Runnable接口和Thread类
2018-07-10 21:42 400Java支持内置的多线程机制。 Java语言包中的Runnab ... -
并发程序设计
2018-07-09 17:22 276并发程序设计 1.顺序程 ... -
线程介绍
2018-07-09 16:55 298线程 1.引入线程机制的 ... -
进程介绍
2018-07-09 15:38 379进程 进程的定义和属性 进程是一个可并发执行的 ... -
多线程
2018-07-09 14:31 313...
相关推荐
视频课程下载——C#多线程与线程同步机制高级实战课程
小实验一:编写一个没有线程同步机制的程序,调试程序,观察在执行程序的过程中,出现的问题并解答原因 小实验二:使用Windows互斥信号量操作函数解决上述线程并发问题,并分析、尝试和讨论线程执行体中有关信号量...
Java 线程同步机制中 synchronized 关键字的理解 Java 的线程同步机制是为了解决多个线程共享同一片存储空间所带来的访问冲突问题。其中,synchronized 关键字是 Java 语言中解决这种冲突的重要机制。 ...
操作系统实验 线程同步机制 Nachos 操作系统实验报告中,主要实现了锁机制和条件变量,并利用这些同步机制实现几个基础工具类。下面是该实验报告的详细知识点: 一、锁机制 锁机制是操作系统中最基本的同步机制...
Java多线程同步机制研究分析 Java多线程同步机制是Java编程语言中的一种机制,它允许多个线程同时执行,提高了系统资源的利用率和安全性。但是,多线程中最重要的问题是线程的同步和共享资源的访问保护。本文通过对...
操作系统中的线程同步机制是确保多个线程在访问共享资源时能够有序进行,避免数据竞争和混乱的关键技术。本实验通过模拟银行账户转账操作来演示线程同步的重要性,并使用不同的同步机制进行对比。 实验目的旨在让...
操作系统线程同步机制实验报告 一、线程同步机制的重要性 在操作系统中,多线程编程是非常常见的。然而,如果不采取任何线程同步措施,多线程之间将会出现数据不一致的问题。通过实验,我们可以看到,如果不采取...
JNI(Java Native Interface)是Java平台提供的一种标准接口,允许Java代码和其他语言写的代码进行交互。在多线程环境中,当涉及到与本地代码...理解和掌握JNI的多线程同步机制对于Java开发者深入系统级编程至关重要。
"Java多线程同步机制的应用分析" Java多线程同步机制的应用分析是指在Java语言中,如何使用同步机制来保护临界区,以避免多线程之间的冲突和错误。该机制通过管程机制和同步语法来保护临界区,使得多线程可以安全...
本篇文章将深入探讨线程同步机制以及如何使用事件对象来实现这一目标。 首先,线程同步的目的是确保在同一时刻只有一个线程可以访问特定的共享资源或执行某段关键代码。这有助于避免竞态条件和死锁等并发问题。常见...
Posix线程同步机制及其在电网监控系统中的应用借鉴 Posix线程同步机制是指在 Unix/Linux 平台上,使用多线程技术来实现多计算任务的并发处理,并解决任务间需要大量数据通信的问题。本文对 Posix 线程同步机制进行...
Windows线程同步机制实验报告 Windows线程同步机制是操作系统中的一种重要机制,用于解决多线程程序中的同步问题。该机制可以确保线程安全地访问共享资源,避免因线程之间的竞争和冲突而导致的错误。 在本实验中,...
Windows 线程同步机制实验报告 操作系统实验报告—Windows 线程同步机制主要涵盖了 Windows 操作系统中的线程同步机制,包括互斥体、事件、关键区、信号量等。实验报告通过 C++/C# 语言在 Microsoft Visual Studio ...
### 操作系统线程同步机制实验报告知识点解析 #### 实验背景与意义 在现代操作系统中,线程同步是一项至关重要的技术。随着多核处理器的普及以及多线程编程的广泛应用,有效地管理线程间的竞争成为了提高软件性能...
操作系统线程同步机制是计算机科学中一个非常重要的概念,它是保证操作系统正确高效运行的关键技术之一。在多任务操作系统中,线程同步机制能够保证多个线程按照预定顺序执行,避免出现数据不一致或者资源竞争等问题...
线程同步机制是多线程编程中的核心概念,它用于协调多个并发执行的线程,确保数据的一致性和完整性,防止出现竞态条件、死锁等并发问题。在多线程环境中,当多个线程访问共享资源时,如果没有适当的同步控制,可能会...
### Java多线程同步机制在售票系统的实现 #### 一、引言 随着计算机硬件的发展,多核处理器已经成为主流配置,这为多线程编程提供了更广阔的应用场景。多线程能够充分利用多核处理器的优势,提高程序的并发性和...
Java多线程同步机制及其应用是Java编程中至关重要的一环,尤其在开发高并发、高性能的应用程序时,理解并掌握这些机制是必不可少的。本文档详细介绍了Java中多线程的相关概念、创建方式、线程管理、同步机制以及一个...
Python中的线程同步机制是为了在多线程环境中确保对共享资源的有序访问,避免出现竞态条件和数据不一致的情况。在上述例子中,我们看到了一个典型的线程同步问题及其解决方案。 首先,让我们理解什么是线程竞态条件...