当多线程去同时抢占CPU资源时,有多线程的安全问题。这时候就需要将线程同步。线程同步有俩个方法。

1.同步代码块(synchronize),同步代码块需要同步监视器,同步监视器是针对对象进行操作。什么对象时共享的,就可以给他加上同步监视器。

  1. package com.bjsxt.ticker;
  2. public class Ticket implements Runnable {
  3. private int ticket=5;
  4. @Override
  5. public void run() {
  6. for (int i = 0; i <100; i++) {//假设100个人再买票
  7. synchronized (this) {
  8. if (ticket > 0) {
  9. System.out.println(Thread.currentThread().getName()+"正在卖第"+(ticket--)+"票");
  10. }
  11. }
  12. try {
  13. Thread.sleep(30);
  14. } catch (InterruptedException e) {
  15. // TODO Auto-generated catch block
  16. e.printStackTrace();
  17. }
  18. }
  19. }
  20. }
  1. package com.bjsxt.ticker;
  2. public class TestTicket01 {
  3. public static void main(String[] args) {
  4. Ticket t=new Ticket();
  5. Thread t1=new Thread(t,"A窗口");
  6. Thread t2=new Thread(t,"B窗口");
  7. Thread t3=new Thread(t,"C窗口");
  8. //启动线程
  9. t1.start();
  10. t2.start();
  11. t3.start();
  12. }
  13. }

打印输出结果:

2.第二种就是同步方法:

  1. package com.bjsxt.ticker;
  2. public class Ticket1 implements Runnable {
  3. private int ticket=5;
  4. @Override
  5. public void run() {
  6. for (int i = 0; i <100; i++) {//假设100个人再买票
  7. this.saleTicket();
  8. try {
  9. Thread.sleep(30);
  10. } catch (InterruptedException e) {
  11. // TODO Auto-generated catch block
  12. e.printStackTrace();
  13. }
  14. }
  15. }
  16. private synchronized void saleTicket() {//同步方法不需要指定同步监视器,同步监视器只能是当前对象this
  17. if (ticket > 0) {
  18. System.out.println(Thread.currentThread().getName()+"正在卖第"+(ticket--)+"票");
  19. }
  20. }
  21. }
  1. package com.bjsxt.ticker;
  2. public class TestTicket01 {
  3. public static void main(String[] args) {
  4. Ticket1 t=new Ticket1();
  5. Thread t1=new Thread(t,"A窗口");
  6. Thread t2=new Thread(t,"B窗口");
  7. Thread t3=new Thread(t,"C窗口");
  8. //启动线程
  9. t1.start();
  10. t2.start();
  11. t3.start();
  12. }
  13. }

运行结果:

进行对比,我们将没有用线程同步的程序拿过来看看:

  1. package com.bjsxt.ticker;
  2. public class Ticket2 implements Runnable {
  3. private int ticket=5;
  4. @Override
  5. public void run() {
  6. for (int i = 0; i <100; i++) {//假设100个人再买票
  7. if (ticket > 0) {
  8. try {
  9. Thread.sleep(300);
  10. } catch (InterruptedException e) {
  11. // TODO Auto-generated catch block
  12. e.printStackTrace();
  13. }
  14. System.out.println(Thread.currentThread().getName()+"正在卖第"+(ticket--)+"票");
  15. }
  16. }
  17. }
  18. }
  1. package com.bjsxt.ticker;
  2. public class TestTicket01 {
  3. public static void main(String[] args) {
  4. Ticket2 t=new Ticket2();
  5. Thread t1=new Thread(t,"A窗口");
  6. Thread t2=new Thread(t,"B窗口");
  7. Thread t3=new Thread(t,"C窗口");
  8. //启动线程
  9. t1.start();
  10. t2.start();
  11. t3.start();
  12. }
  13. }

运行结果:

可以看到,没有用同步方法,连0和-1都出来了,甚至还有俩个窗口卖同一张票的。这就是多线程没有用同步方法的线程安全。

Java修炼——线程同步的俩种方法的更多相关文章

  1. java中线程同步的几种方法

    1.使用synchronized关键字 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法.在调用该方法前,需要获得内置锁,否则就处于阻塞状态. 注: synchro ...

  2. JAVA之线程同步的三种方法

    最近接触到一个图片加载的项目,其中有声明到的线程池等资源需要在系统中线程共享,所以就去研究了一下线程同步的知识,总结了三种常用的线程同步的方法,特来与大家分享一下.这三种方法分别是:synchroni ...

  3. Linux下线程同步的几种方法

    Linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量和信号量. 一.互斥锁(mutex) 锁机制是同一时刻只允许一个线程执行一个关键部分的代码.  1. 初始化锁 int pthrea ...

  4. 归纳一下:C#线程同步的几种方法

    转自原文 归纳一下:C#线程同步的几种方法 我们在编程的时候,有时会使用多线程来解决问题,比如你的程序需要在后台处理一大堆数据,但还要使用户界面处于可操作状态:或者你的程序需要访问一些外部资源如数据库 ...

  5. Java中实现线程同步的三种方法

    实现同步的三种方法 多线程共享数据时,会发生线程不安全的情况,多线程共享数据必须同步. 实现同步的三种方法: 使用同步代码块 使用同步方法 使用互斥锁ReetrantLock(更灵活的代码控制) 代码 ...

  6. java多线程二之线程同步的三种方法

          java多线程的难点是在:处理多个线程同步与并发运行时线程间的通信问题.java在处理线程同步时,常用方法有: 1.synchronized关键字. 2.Lock显示加锁. 3.信号量Se ...

  7. Java多线程--实现同步的9种方法

    我们通常说的保持同步,其实就是对共享资源的保护.在单线程模型中, 我们永远不用担心"多个线程试图同时使用同一个资源的问题", 但是有了并发, 就有可能发生多个线程竞争同一个共享资源 ...

  8. C#线程同步的几种方法

    一.volatile关键字 volatile是最简单的一种同步方法,当然简单是要付出代价的.它只能在变量一级做同步,volatile的含义就是告诉处理器, 不要将我放入工作内存, 请直接在主存操作我. ...

  9. 【转】 Linux 线程同步的三种方法

    线程的最大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点.linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量和信号量. 一.互斥锁(mutex) 通过锁机制实现线程间的 ...

随机推荐

  1. html5基本页面

    html5基本页面 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  2. jQuery源码分析--为什么在参数列表中传入undefined

    (function(window, undefined){ //jQuery code; })(window); 为什么要传入undefined? 1.没有传入undefined: <!DOCT ...

  3. starUML 3.0.2文件 百度云

    文件百度云---链接:https://pan.baidu.com/s/1BVX9Ze40bkgd3k_4WFb99A 提取码:t7kj 使用方法:将starUML安装目录(一般为 C:\Program ...

  4. Unity中用Mesh画一个圆环(二)

    中目标-生成完整面 在之前的内容中我们已经成功生成了一个面,接下来我们要生成剩下的面就很容易了. 我们把之前生成的面当作顶面,接着我们来生成底面. 还记得前面说过\(\color{#1E90FF}{D ...

  5. PHP 从另一个角度来分析 Laravel 框架的依赖注入功能

    从根本上说,依赖注入不是让对象创建一个依赖关系,也不是让工厂对象去创建对象,而是将所需的依赖变成一个外部对象,使之成为一个"某些人的问题” 你为"某些人的问题”注入了类的依赖关系. ...

  6. 【译】利用Lombok消除重复代码

    当你在写Getter和Setter时,一定无数次的想过,为什么会有POJO这么烂的东西.你不是一个人!(不是骂人-)无数的开发人员花费了大量的时间来写这种样板代码,而他们本来可以利用这些时间做出更有价 ...

  7. 逆向分析objc,所有类的信息都能在动态调试中获取。

    因为objc是动态绑定的,程序运行时必须知道如何绑定,依靠的就是类描述.只要知道类描述是如何组织的就可以获取一切有用的信息.不知道是幸运还是不幸,这些信息全部都在运行的程序中.即使没有IDA这样的工具 ...

  8. CSS如何设置列表样式属性,看这篇文章就够用了

    列表样式属性 在HTML中有2种列表.无序列表和有序列表,在工作中无序列表比较常用,无序列表就是ul标签和li标签组合成的称之为无序列表,那什么是有序列表呢?就是ol标签和li标签组合成的称之为有序列 ...

  9. rhel-6.3-i386安装samba

    1.安装samba 1).安装软件 rpm –ivh /mnt/Packages/samba-3.5.10-125.el6.i686.rpm 2).创建用户 useradd myadmin 3).设置 ...

  10. 在input输入值改变reducer里的值

    输入值改变reducer里的值 通过store.dispatch传入reducer中,函数的第二个参数可以接收到 在reducer中 在todolist文件中 然后在把this.state中的值改变