一、线程安全问题产生前提:
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. ubuntu下可用的串口调试工具--cutecom

    今天在ubuntu下要用到串口发送16进制数据,百度了很多工具,觉得minicom和cutecom都不错,比较直观是cutecom,所以就介绍下cutecom. 安装: 输入 $ sudo apt-g ...

  2. Spring cloud学习--Zuul02

    过滤器 Zuul包括两部分内容:请求的路由和过滤.而实际上请求的路由也是通过过滤器实现的,例如理由映射主要通过pre类型的过滤器完成,它将请求路径与配置的路由规则进行匹配,找到需要转发的目标地址:请求 ...

  3. [功能集锦] 002 - mysql查询数据库字典+导出+样式一键整合至excel

    写在前面: 因为工作时候经常遇到半路接手项目的情况,由于年代久远,数据库字典这块经常缺失.故写此篇,以便复用,也希望对大家有点帮助. 随笔内容不高级,如有不妥,不吝指正. 20190730-加了一些简 ...

  4. [Bzoj3224][Tyvj1728] 普通平衡树(splay/无旋Treap)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3224 平衡树入门题,学习学习. splay(学习yyb巨佬) #include<b ...

  5. [51nod 1681]公共祖先(dfs序+线段树合并)

    [51nod 1681]公共祖先(dfs序+线段树合并) 题面 给出两棵n(n<=100000)个点的树,对于所有点对求它们在两棵树中公共的公共祖先数量之和. 如图,对于点对(2,4),它们在第 ...

  6. tomcat安装分享

    安装Tomcat前需要安装JDK 安装的jdk1.8   解压   在vim /etc/profile下面添加以下内容 export JAVA_HOME=/jdk/jdk1.8.0_111export ...

  7. 找回git rebase --skip消失的代码

    1.git reflog操作,查看提交的历史记录,找到自己的提交 2.强制回退到上一次提交:git reset --hard  791a1fc 或者 git reset --hard  HEAD@{2 ...

  8. Spring Cloud Contract简介

    转载:https://www.jianshu.com/p/e3277824a10a 和dummy service一样 Spring Cloud Contract是个啥? Spring Cloud Co ...

  9. 240-4C6678_K7_DDR3_VPX高速信号处理板

    4C6678_K7_DDR3_VPX高速信号处理板 4C6678_K7_DDR3_VPX板为基于TI   多核DSP TMS320C6678的通用处理板卡.板卡满足OpenVPX平台标准,可为雷达.电 ...

  10. 二、RabbitMQ操作

    1.RabbitMQ发送与接收. 2.RabbitMQ发送与接收. 3.RabbitMQ发送与接收.