一、线程安全问题产生前提:
1、多线程操作共享数据
2、线程任务中有多条代码

 class Ticket implements Runnable
{
//2.共享数据
private int num = 100; public void run()
{
while(true)
{
//3.多条代码
if(num > 0)
{
try{Thread.sleep(10);}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"==="+num--);
}
}
}
} class TicketDemo
{
public static void main(String[] args)
{
Ticket t = new Ticket();
//1.多线程操作同一个对象
Thread t1 =new Thread(t);
Thread t2 =new Thread(t);
Thread t3 =new Thread(t);
Thread t4 =new Thread(t); t1.start();
t2.start();
t3.start();
t4.start();
}
}

运行结果:

出现线程安全问题了

二、解决线程安全问题

解决线程安全问题的两种方式:

①、同步代码块

格式:

 synchronized(对象)
{
  //需要被同步的代码;
... ...
}

解决上面线程安全问题的代码:

 class Ticket implements Runnable
{
//2.共享数据
private int num = 100;
//同步锁:对象
private Object o=new Object();
public void run()
{
while(true)
{
synchronized(o)
{
//3.多条代码
if(num > 0)
{
try{Thread.sleep(10);}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"==="+num--);
}
}
}
}
}

结果:

解决原理:多线程在使用同步代码块时,使用了同一个同步锁(Object的对象)

②、同步函数

格式:

 public synchronized 方法返回值类型 方法名(参数列表)
{
... ...
}

2.1、非静态同步函数

代码:

 class Ticket implements Runnable
{
//2.共享数据
private int num = 100;
//同步锁:对象
//private Object o=new Object();
public void run()
{
while(true)
{
/*
synchronized(o)
{
//3.多条代码
if(num > 0)
{
try{Thread.sleep(10);}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"==="+num--);
}
}
*/
show();
}
}
public synchronized void show()
{
//3.多条代码
if(num > 0)
{
try{Thread.sleep(10);}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"==="+num--);
}
}
}

结果:

2.2、静态同步函数

代码:

 class Ticket implements Runnable
{
//2.共享数据
private static int num = 100;
//同步锁:对象
//private Object o=new Object();
public void run()
{
while(true)
{
/*
synchronized(o)
{
//3.多条代码
if(num > 0)
{
try{Thread.sleep(10);}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"==="+num--);
}
}
*/
show();
}
}
public static synchronized void show()
{
//3.多条代码
if(num > 0)
{
try{Thread.sleep(10);}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"==="+num--);
}
}
}

结果:

总结:
同步的好处:解决线程的安全问题
同步的弊端:效率低,因为同步外的线程都会判断同步锁
同步的前提:必须有多个线程使用同一个同步锁(synchronized(同步锁:对象))
同步代码块:可以指定任意对象作为同步锁
同步函数:非静态同步函数的同步锁为当前类对象(this),静态同步函数为当前类的字节码对象(类名.class或this.getClass())

Java学习之多线程(线程安全问题及线程同步)的更多相关文章

  1. Java学习笔记-多线程-创建线程的方式

    创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...

  2. 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁

    什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...

  3. 2019/3/7 Java学习之多线程(基础)

    Java学习之多线程 讲到线程,就必须要懂得进程,进程是相当于一个程序的开始到结束,而线程是依赖于进程的,没有进程,就没有线程.线程也分主线程和子线程,当在主线程开启子线程时,主线程结束,而子线程还可 ...

  4. java学习笔记 --- 多线程(线程安全问题——同步代码块)

    1.导致出现安全问题的原因: A:是否是多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据 2.解决线程安全问题方法: 同步代码块: synchronized(对象){ 需要同步的代码; ...

  5. 0041 Java学习笔记-多线程-线程池、ForkJoinPool、ThreadLocal

    什么是线程池 创建线程,因为涉及到跟操作系统交互,比较耗费资源.如果要创建大量的线程,而每个线程的生存期又很短,这时候就应该使用线程池了,就像数据库的连接池一样,预先开启一定数量的线程,有任务了就将任 ...

  6. 0040 Java学习笔记-多线程-线程run()方法中的异常

    run()与异常 不管是Threade还是Runnable的run()方法都没有定义抛出异常,也就是说一条线程内部发生的checked异常,必须也只能在内部用try-catch处理掉,不能往外抛,因为 ...

  7. 0039 Java学习笔记-多线程-线程控制、线程组

    join线程 假如A线程要B线程去完成一项任务,在B线程完成返回之前,不进行下一步执行,那么就可以调用B线程的join()方法 join()方法的重载: join():等待不限时间 join(long ...

  8. 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题

    调用同步锁的wait().notify().notifyAll()进行线程通信 看这个经典的存取款问题,要求两个线程存款,两个线程取款,账户里有余额的时候只能取款,没余额的时候只能存款,存取款金额相同 ...

  9. 0036 Java学习笔记-多线程-创建线程的三种方式

    创建线程 创建线程的三种方式: 继承java.lang.Thread 实现java.lang.Runnable接口 实现java.util.concurrent.Callable接口 所有的线程对象都 ...

随机推荐

  1. nodejs基础-nvm和npm

    nvm npm 更新 npm install npm@latest -g 本地安装 npm install 包名称 require(”包名“) 全局安装 npm install 包名 -g 可以直接作 ...

  2. pdo getLastInertID()无结果

    该函数只返回具有自增约素的表, 不然返回0. 使用exec()得到的是受影响的行数.

  3. Java数组相关算法一

    一.数组反转 1.方法一:创建新数组 int[] arr = {6,29,0,4,3}; int[] arr2 = new int[arr.length]; for (int i = 0; i < ...

  4. 【JAVA】 03-Java中的异常和包的使用

    链接: 笔记目录:毕向东Java基础视频教程-笔记 GitHub库:JavaBXD33 目录: <> <> 内容待整理: 异常 异常和错误的发生和区别 异常:java运行期间发 ...

  5. npm run dev 报错:Error: Cannot find module 'webpack-cli/bin/config-yargs'

    使用 npm run dev 时报错: Error: Cannot find module 'webpack-cli/bin/config-yargs' 原因是找不到webpack-cli这个包,使用 ...

  6. 关于在IE下JavaScript的 Stack overflow at line 错误可能的原因

    该错误只在IE中出现,出现该提示的原因主要有两种: 1. 重定义了系统的触发事件名称作为自定义函数名如:  onclick / onsubmit …  都是系统保留的事件名称,不允许作为重定义函数名称 ...

  7. Trait这个类的特性

    php从以前到现在一直都是单继承的语言,无法同时从两个基类中继承属性和方法,为了解决这个问题,php出了Trait这个特性 用法:通过在类中使用use 关键字,声明要组合的Trait名称,具体的Tra ...

  8. vue下超级滚动条perfect-scrollbar(在特定框架里使用一款并非为该框架定制的库/插件)

    点我查看

  9. (解决某些疑难杂症)Ubuntu16.04 + NVIDIA显卡驱动 + cuda10 + cudnn 安装教程

    一.NVIDIA显卡驱动 打开终端,输入: sudo nautilus 在新打开的文件夹中,进入以下路径(不要用命令行): 左下角点计算机,lib,modules 这时会有几个文件夹,对每个文件夹都进 ...

  10. java ArrayList练习题

    package java06; /* *随机产生6的1——33的数字,并存储到列表中,再进行遍历 * */ import java.util.ArrayList; import java.util.R ...