如何判断一个程序是否会有线程安全问题?

如何判断一个程序是否会有线程安全问题?

/*
 * 如何解决线程安全问题呢?
 * 
 * 要想解决问题,就要知道哪些原因会导致出问题:(而且这些原因也是以后我们判断一个程序是否会有线程安全问题的依据)
 *         A:是否是多线程环境
 *         B:是否有共享数据
 *         C:是否有多条语句操作共享数据
 * 
 * 我们来回想一下我们的程序有没有上面的问题呢?
 *         A:是否是多线程环境        是
 *         B:是否有共享数据        是
 *         C:是否有多条语句操作共享数据  是
 * 
 * 由此可见我们的程序出现问题是正常的,因为它满足出问题的条件。
 * 
 * 接下来才是我们要想想如何解决问题呢?
 *         A和B的问题我们改变不了,我们只能想办法去把C问题改变一下。
 * 
 * 
 * 思想:
 *         把多条语句操作共享数据的代码部分给包起来(锁起来),让某个线程在执行的时候,别人不能来执行。
 *         (即:把多个语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可)
 * 
 *         问题是:我们不知道怎么包啊?其实我也不知道啊!但是Java给我们提供了:同步机制。
 * 
 * 生活举例:
 *         火车上厕所。
 *         医院挂号看病。
 * 
 * 同步代码块:
 *         synchronized(对象) {
 *             需要同步的代码;
 *         }
 * 
 *         A:对象是什么呢?
 *             我们可以随便创建一个对象先试试,例如:new Object()。
 *         B:需要同步的代码是哪些呢?
 *             把多条语句操作共享数据的代码部分给包起来(锁起来)。
 * 
 *         注意:
 *             同步可以解决安全问题的根本原因就在那个对象上。该对象如同锁的功能。
 *             多个线程必须是同一把锁。
 * 
 */

示例代码如下:

 1 package cn.itcast_09;
 2 
 3 /*
 4  * 如何解决线程安全问题呢?
 5  * 
 6  * 要想解决问题,就要知道哪些原因会导致出问题:(而且这些原因也是以后我们判断一个程序是否会有线程安全问题的依据)
 7  *         A:是否是多线程环境
 8  *         B:是否有共享数据
 9  *         C:是否有多条语句操作共享数据
10  * 
11  * 我们来回想一下我们的程序有没有上面的问题呢?
12  *         A:是否是多线程环境            是
13  *         B:是否有共享数据            是
14  *         C:是否有多条语句操作共享数据    是
15  * 
16  * 由此可见我们的程序出现问题是正常的,因为它满足出问题的条件。
17  * 
18  * 接下来才是我们要想想如何解决问题呢?
19  *         A和B的问题我们改变不了,我们只能想办法去把C问题改变一下。
20  * 
21  * 
22  * 思想:
23  *         把多条语句操作共享数据的代码部分给包起来(锁起来),让某个线程在执行的时候,别人不能来执行。
24  *         (即:把多个语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可)
25  * 
26  *         问题是:我们不知道怎么包啊?其实我也不知道啊!但是Java给我们提供了:同步机制。
27  * 
28  * 生活举例:
29  *         火车上厕所。
30  *         医院挂号看病。
31  * 
32  * 同步代码块:
33  *         synchronized(对象) {
34  *             需要同步的代码;
35  *         }
36  * 
37  *         A:对象是什么呢?
38  *             我们可以随便创建一个对象先试试,例如:new Object()。
39  *         B:需要同步的代码是哪些呢?
40  *             把多条语句操作共享数据的代码部分给包起来(锁起来)。
41  * 
42  *         注意:
43  *             同步可以解决安全问题的根本原因就在那个对象上。该对象如同锁的功能。
44  *             多个线程必须是同一把锁。
45  * 
46  */
47 public class SellTicketDemo {
48     public static void main(String[] args) {
49         // 创建资源对象
50         SellTicket st = new SellTicket();
51 
52         // 创建三个线程对象
53         Thread t1 = new Thread(st, "窗口1");
54         Thread t2 = new Thread(st, "窗口2");
55         Thread t3 = new Thread(st, "窗口3");
56 
57         // 启动线程
58         t1.start();
59         t2.start();
60         t3.start();
61     }
62 }
 1 package cn.itcast_09;
 2 
 3 public class SellTicket implements Runnable {
 4     // 为了让多个线程对象共享这100张票和锁对象(同一把锁),我们应该用静态修饰。
 5     // 定义100张票
 6     private int tickets = 100;
 7     // 创建锁对象
 8     private Object obj = new Object();
 9 
10     /*
11     @Override
12     public void run() {
13         while (true) {
14             synchronized(new Object()){ // 我们可以随便创建一个对象先试试,例如:new Object()。
15                 if (tickets > 0) {
16                     try {
17                         Thread.sleep(100); 
18                     } catch (InterruptedException e) {
19                         e.printStackTrace();
20                     }
21                     System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票");
22                 }
23             }
24         }
25     }
26     */
27     
28     @Override
29     public void run() {
30         while (true) {
31             synchronized (obj) {
32                 if (tickets > 0) {
33                     try {
34                         Thread.sleep(100);
35                     } catch (InterruptedException e) {
36                         e.printStackTrace();
37                     }
38                     System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票");
39                 }
40             }
41         }
42     }
43 }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技巅

GlusterFS之内存池(mem-pool)使用实例分析

1906
来自专栏ccylovehs

JDK动态代理与CGLib动态代理

JDK1.3以后java提供了动态代理技术,允许开发者在运行期创建接口的代理实例,动态代理是实现AOP的绝好底层技术。

3971
来自专栏Ryan Miao

Optional乱用Empty之No value present

前言 看到好多文章都是推荐采用Optinal的,而经常我遇到问题的时候就想:如果设计成optional的话就不会忽略这种NullPointException错误...

3326
来自专栏专注 Java 基础分享

基于 JDK 的动态代理机制

874
来自专栏JavaEdge

探究synchronized底层原理(基于JAVA8源码分析)实现原理同步代码块Mark WordMonitor

4365
来自专栏JackeyGao的博客

Django小技巧08: Blank or Null

Django Model API 中提供了blank和null两个参数, 非常容易混淆。当我第一次使用 Django 的时候, 总是不能恰当的使用这两个参数。

733
来自专栏运维技术迷

Redis全局命令

redis有5种数据结构,他们是键值对中的值,对于键来说有一些通用的命令。 查看所有键 语法:keys * [root@vultr ~]# redis-cli ...

3457
来自专栏hbbliyong

C学习笔记(1)-结构体、预处理与多文件结构程序设计

一、结构体的定义与使用 #include <stdio.h> //定义结构体(类似模板) typedef struct { char name[50]; ...

2954
来自专栏北京马哥教育

开发神技能 | Python Mock 的入门

运维行业正在变革,推荐阅读:30万年薪Linux运维工程师成长魔法 Mock是什么 Mock这个词在英语中有模拟的这个意思,因此我们可以猜测出这个库的主要功能是...

3609
来自专栏Python攻城狮

Python-线程1.线程2.多线程-threading3.主线程会等待所有的子线程结束后才结束4.查看线程数量 5.threading注意点 6.多线程-共享全局变量 7.列表当做实参传递到线程中

thread.start_new_thread(function,args[,kwargs])

3643

扫码关注云+社区

领取腾讯云代金券