线程同步——并发控制

并发:同一个对象多个线程同时操作

线程不安全: 数据有负数、相同

开辟多线程,每个线程都有自己的工作空间  与 主存 进行交互

/***   线程不安全: 数据有负数、相同* @author Administrator**/
public class UnsafeTest01 {public static void main(String[] args) {//一份资源UnsafeWeb12306 web=new UnsafeWeb12306();System.out.println(Thread.currentThread().getName());//多个代理new Thread(web,"马畜").start();new Thread(web,"码农").start();new Thread(web,"码蝗").start();}
}
class UnsafeWeb12306 implements Runnable{//票数private int ticketNums=10;private boolean flag=true;@Overridepublic void run() {while(flag) {test();}}private void test() {if(ticketNums<0) {flag=false;return;}//模拟延时try {Thread.sleep(200);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(Thread.currentThread().getName()+"-->"+ticketNums--);}
}


线程不安全:取钱

/*** 线程不安全:取钱* @author Administrator**/
public class UnsafeTest02 {public static void main(String[] args) {//账户Account account=new Account(100, "结婚礼金");Drawing you=new Drawing(account, 80, "可悲的你");Drawing wife=new Drawing(account, 90, "happy的她");you.start();wife.start();}
}//账户
class Account{int money; //金额String name; //名称public Account(int money, String name) {this.money = money;this.name = name;}
}
//模拟取款
class Drawing extends Thread{Account account;  //取钱的账户int drawingMoney;  //取的钱数int packetTotal;  //口袋的总数public Drawing(Account account, int drawingMoney,String name) {super(name);this.account = account;this.drawingMoney = drawingMoney;}@Overridepublic void run() {if(account.money-drawingMoney<0) {return;}try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}account.money -= drawingMoney;packetTotal+=drawingMoney;System.out.println(this.getName()+"-->账户余额为:"+account.money);System.out.println(this.getName()+"-->口袋的钱为:"+packetTotal);}}

线程不安全:操作容器

import java.util.ArrayList;
import java.util.List;/*** 线程不安全:操作容器* @author Administrator**/
public class UnsafeTest03 {public static void main(String[] args) {List<String> list=new ArrayList<String>();for(int i=0;i<1000;i++) {new Thread(()->{list.add(Thread.currentThread().getName());}).start();}System.out.println(list.size());}
}


什么是线程同步

▪ 同步问题的提出

现实生活中,我们会遇到“同一个资源,多个人都想使用”的问题。 比如:教室里,只有一台电脑,多个人都想使用。天然的解决办法就是,在电脑旁边,大家排队。前一人使用完后,后一人再使用。

线程同步的概念

处理多线程问题时,多个线程访问同一个对象,并且某些线程还想修改这个对象。 这时候,我们就需要用到“线程同步”。 线程同步其实就是一种等待机制,多个需要同时访问此对象的线程进入这个对象的等待池形成队列,等待前面的线程使用完毕后,下一个线程再使用。

由于同一进程的多个线程共享同一块存储空间,在带来方便的同时,也带来了访问冲突的问题。为了保证数据在方法中被访问时的正确性,在访问时加入锁机制(synchronized),当一个线程获得对象的排他锁,独占资源,其他线程必须等待,使用后释放锁即可。

存在以下问题:1. 一个线程持有锁会导致其他需要此锁的线程挂起

2. 在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题

3. 如果一个优先级高的线程等待一个优先级低的线程释放会导致优先级倒置,引起性能问题。

由于可以通过 private 关键字来保证数据对象只能被方法访问,所以我们只需针对方法提出一套机制,这套机制就是synchronized关键字,它包括两种用法:synchronized 方法和 synchronized 块。

▪ synchronized 方法

通过在方法声明中加入 synchronized关键字来声明,语法如下:

synchronized 方法控制对“对象的类成员变量”的访问:每个对象对应一把锁,每个 synchronized 方法都必须获得调用该方法的对象的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。

synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率。

线程安全: 在并发时保证数据的正确性、效率尽可能高
 * synchronized
 * 1、同步方法
 * 2、同步块

/*** * 线程安全: 在并发时保证数据的正确性、效率尽可能高* synchronized* 1、同步方法* 2、同步块* @author Administrator**/
public class SynTest01 {public static void main(String[] args) {//一份资源SafeWeb12306 web =new SafeWeb12306();//多个代理new Thread(web,"码畜").start();new Thread(web,"码农").start();new Thread(web,"码蟥").start();;}}class SafeWeb12306 implements Runnable{//票数private int ticketNums =10;private boolean flag = true;@Overridepublic void run() {while(flag) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}test();}} //线程安全  同步public synchronized void test() {if(ticketNums<=0) {flag = false;return ;}//模拟延时try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"-->"+ticketNums--);}
}


//目标不对锁定失败

同步块:synchronized(obj){}  obj  称为 同步监视器

块:局部块 构造块 静态块  普通块

同步方法中无需指定同步监视器,因为同步方法的同步监视器是this即对象本身,或class即类的模子

/*** 线程安全: 在并发时保证数据的正确性、效率尽可能高* synchronized* 1、同步方法* 2、同步块 ,目标更明确* @author Administrator**/
class Account{int money;String name;public Account(int money, String name) {this.money = money;this.name = name;}
}public class SynBlockTest01 {public static void main(String[] args) {      //账户Account account =new Account(100,"结婚礼金");SynDrawing you = new SynDrawing(account,80,"可悲的你");SynDrawing wife = new SynDrawing(account,90,"happy的她");you.start();wife.start();}
} //模拟取款 线程安全
class SynDrawing extends Thread{Account account ; //取钱的账户int drawingMoney ;//取的钱数int packetTotal ; //口袋的总数  public SynDrawing(Account account, int drawingMoney,String name) {super(name);this.account = account;this.drawingMoney = drawingMoney;}@Overridepublic void run() {test() ;}//目标锁定accountpublic  void test() {//提高性能if(account.money<=0) {return ;}//同步块synchronized(account) {if(account.money -drawingMoney<0) {return; }try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}account.money -=drawingMoney;packetTotal +=drawingMoney;System.out.println(this.getName()+"-->账户余额为:"+account.money);System.out.println(this.getName()+"-->口袋的钱为:"+packetTotal);}}
}



线程安全:操作容器

import java.util.ArrayList;
import java.util.List;/*** 线程安全:操作容器* @author Administrator**/
public class SynBlockTest02 {public static void main(String[] args) throws InterruptedException {List<String> list=new ArrayList<String> ();for(int i=0;i<10000;i++) {new Thread(()-> {//同步块synchronized (list) {list.add(Thread.currentThread().getName());}}).start();}Thread.sleep(1000);System.out.println(list.size());}
}

Java的知识点31——线程同步相关推荐

  1. Java并发编程之线程同步

    线程安全就是防止某个对象或者值在多个线程中被修改而导致的数据不一致问题,因此我们就需要通过同步机制保证在同一时刻只有一个线程能够访问到该对象或数据,修改数据完毕之后,再将最新数据同步到主存中,使得其他 ...

  2. java的知识点34——线程通信 || 生产者与消费者问题

    线程通信 应用场景:生产者和消费者问题 • 假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取走消费 • 如果仓库中没有产品,则生产者将产品放入仓库,否则停止生产并等待, ...

  3. JAVA并发编程3_线程同步之synchronized关键字

    在上一篇博客里讲解了JAVA的线程的内存模型,见:JAVA并发编程2_线程安全&内存模型,接着上一篇提到的问题解决多线程共享资源的情况下的线程安全问题. 不安全线程分析 public clas ...

  4. java同步通信_java-线程-线程同步通信技术

    源代码如下 public class TranditionalThreadCommunication { /** * @param args */ public static void main(St ...

  5. 【java】Java 中的 Exchanger 线程同步使用方法 线程之间交换数据

    1.概述 转载:https://www.pdai.tech/md/java/thread/java-thread-x-juc-tool-exchanger.html 视频参考:https://www. ...

  6. Java的知识点28——线程的生命周期

    线程的生命周期 一个线程对象在它的生命周期内,需要经历5个状态. 1.  新生状态(New): 用new关键字建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用 ...

  7. Java的知识点30——线程的优先级、终止线程的典型方式、获取线程基本信息的方法

    线程的优先级  1-10 1. NORM_PRIORITY  5 默认  2. MIN_PRIORITY  1  3. MAX_PRIORITY  10 注意:优先级低只是意味着获得调度的概率低.并不 ...

  8. Java的知识点31——封装拷贝、封装释放、实现放大器对声音的放大功能

    封装拷贝.封装释放 package cn.dym;import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; ...

  9. java syncr_JAVA基础—Synchronized线程同步机制

    Synchronize的使用场景 Synchronize可以使用在一下三种场景,对应不同的锁对象 场景 synchronized代码块 synchronized方法 synchronized静态方法 ...

最新文章

  1. rop检查_注意!这几类人一定要定期检查眼底!
  2. flash 多张相片同时移动_Flash时代时代即将终止?早就预料到了
  3. Scala里Unit 与 () Unit的区别
  4. oracle入库的速度能到多少_倒车入库别练复杂了,其实就这两点
  5. python惰性求值的特点_C#教程之C#函数式编程中的惰性求值详解
  6. VC中使用低级音频函数WaveX播放声音文件
  7. ProjectEuler 2
  8. 【设计模式:单例模式】单例模式01:饿汉模式
  9. 索引组织表:万物皆索引
  10. C#编译器对泛型方法调用作类型推断的奇怪问题
  11. 程序员锁死服务器导致公司倒闭,案件终于开庭了
  12. ViewFlipper使用详解
  13. 数字图像处理(matlab版)第三版,数字图像处理及MATLAB实现(第3版)
  14. 存着-在重置电脑时删除了应用
  15. ArcGIS 软件中路网数据的制作,手把手教学
  16. 50页PPT,让你全面了解物联网产业链及发展趋势 | 附下载
  17. 阿里面试题:鹿晗发布恋情,为什么微博挂了?
  18. 一文详解知识图谱关键技术与应用 | 公开课笔记
  19. 学习ARM开发(15)
  20. 基于开源应用快速构建HTAP系统(2)-阿里云开发者社区

热门文章

  1. SoapUI 请求 https 报 javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
  2. Mac python3.x使用HTMLTestRunner.py
  3. 2735:八进制到十进制-poj
  4. tensorflow 使用
  5. AngularJs 常用指令标签
  6. levelDB数据库使用及实例 - 高性能nosql存储数据库
  7. (译)cocos2d-x跨androidios平台开发入门教程
  8. CE6内核启动过程-新角度
  9. c语言 枚举定义变量,C语言之枚举的定义以及测试
  10. 你以为 CSS 只是个简单的布局?装逼指南了解一下