---------------------- ASP.Net+Android+IO开发S、.Net培训、期待与您交流! ---------------------
单个线程操作资源的时候,是不会出现安全问题的,但是如果多个线程操作同一个资源的时候,因为CPU的使用权限是大家平等的,在任何时候都可能执行任意线程的任意语句(在不加锁的情况下),这就会产生线程的安全问题,比如下边代码
package thread; public class TestThread { private static int count; int line = 5; public static void main(String[] args) { TestThread tt = new TestThread(); tt.startThread(); tt.startThread(); } class CountThread implements Runnable { public void run() { while (count < 25) { //synchronized (TestThread.class) { //if(count < 25){ count++; System.out.print(Thread.currentThread().getName() + "--" + count + "\t"); line--; if (line == 0) { System.out.println(); line = 5; } } //} //} } } public void startThread() { new Thread(new CountThread()).start(); } }
运行结果为:
Thread-0--1 Thread-0--3 Thread-0--4 Thread-0--5 Thread-0--6
Thread-0--7 Thread-0--8 Thread-0--9 Thread-0--10 Thread-1--2
Thread-1--12 Thread-1--13 Thread-1--14 Thread-1--15 Thread-1--16
Thread-1--17 Thread-1--18 Thread-1--19 Thread-1--20 Thread-1--21
Thread-1--22 Thread-1--23 Thread-1--24 Thread-0--11 Thread-1--25
明显不符合我们的程序初衷,中间的2无缘无故没了,这就是线程的安全问题了,所以要加入控制代码同步的锁,如下代码
package thread; public class TestThread { private static int count; int line = 5; public static void main(String[] args) { TestThread tt = new TestThread(); tt.startThread(); tt.startThread(); } class CountThread implements Runnable { public void run() { while (count < 25) { synchronized (TestThread.class) { if(count < 25){ count++; System.out.print(Thread.currentThread().getName() + "--" + count + "\t"); line--; if (line == 0) { System.out.println(); line = 5; } } } } } } public void startThread() { new Thread(new CountThread()).start(); } }
运行结果就为:
Thread-0--1 Thread-1--2 Thread-1--3 Thread-1--4 Thread-1--5
Thread-1--6 Thread-0--7 Thread-0--8 Thread-0--9 Thread-0--10
Thread-0--11 Thread-0--12 Thread-0--13 Thread-0--14 Thread-0--15
Thread-0--16 Thread-0--17 Thread-0--18 Thread-0--19 Thread-0--20
Thread-1--21 Thread-1--22 Thread-1--23 Thread-0--24 Thread-0--25
这才是正常的,在程序代码中使用了两次判断count<25,这是因为这样可以让多个程序同时访问count,而不用等别的程序的while循环结束。
同步代码用的锁是一个对象,而且需要同步的代码所用的锁必须是一样的。
(转自CSDN)
- 同步代码块定义方法:
-
- synchronized(对象)//这个对象可以是任意对象,例如Object,这样做是为了减小锁的粒度,建议使用更经济的空byte数组对象做锁。
- //对象如同锁,持有锁的线程可以在同步中执行。没有锁的线程即使获取CPU的执行权,也进不去,因为没有获取锁。
- {
- 需要被同步的代码//这个代码不包括共享数据,只包括判断与结论等不能分割的数据。
- }
- synchronized(对象)//这个对象可以是任意对象,例如Object,这样做是为了减小锁的粒度,建议使用更经济的空byte数组对象做锁。
- 同步的前提:
- 必须有两个或以上的线程。
- 必须是多个线程使用同一个锁。必须保证同步中只能有一个线程在运行。
- 同步的好处:
- 解决了多线程的安全问题。
- 同步的弊端:
- 多个线程需要判断锁,较为消耗资源。
- 哪些时候使用同步?
- 1.明确哪些代码是多线程运行代码。
- 2.明确共享数据。
- 3.明确多线程运行代码中哪些语句是操作共享数据的。
(转自CSDN)
另外,在函数的返回值类型前加上 synchronized声明,则成为同步函数,和同步代码块一个效果
上面的例子只是做到了同步,但是当多个线程对同一资源进行不同操作是,单是同步并不够,因为每个线程的运行条件不一样,比方说对一个仓库的操作,一个往里边加东西的线程需要判断里边有没有装满,一个从里边拿东西的线程则需要判断里边有没有东西,这两个判断都是基于仓库中的资源,所以需要同步,但是如果仓库满的话,那放东西的线程就必须休息一下,即是wait,那它什么时候醒呢?当然是有人叫醒它了,叫醒它的人就是和它有同样同步锁的拿东西的那个线程了,这就是线程的通信基本原理
通信的时候需要注意的问题:
- 有三个以上的线程的时候,判断是否休息的语句用while,因为用if可能会让所有线程等待,if只判断一次。
- 有三个以上的线程的时候,叫醒用notifyAll,这样会避免叫醒的线程正好是和要去睡觉的线程是同一类,然后大家都睡觉了。
这里边的关系用一幅图来表示吧
当然这是最背的情况,实际情况更复杂,需要用配合代码来说明的。
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
详细请查看:http://edu.csdn.net
相关推荐
day01_Object类、常用API day02_Collection、泛型 day03_List、Set、数据结构、Collections day04_Map,斗地主案例 day05_异常,线程 day06_线程、同步 day07_等待与唤醒案例、线程池、Lambda...Java基础小节练习题答案
NULL 博文链接:https://huangminwen.iteye.com/blog/1157983
《Java 基础入门》课后习题答案 第 第 1 章 Java 开发入门 一、填空题 1、 Java EE、Java SE、Java ME 2、 JRE 3、 javac 4、 bin 5、 path、classpath 二、选择题 1、ABCD 2、C 3、D 4、B 5、B 三、简答题 1、 面向...
vc++ 多线程教程---线程通信--利用事件对象,线程同步--使用信号量,线程同步--使用互斥量,线程同步--使用临界区
4.客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。各类型客户在其...
01大数据面试复习----Java基础---集合类、多线程、JVM.zip
黑马程序员_张孝祥_Java多线程与并发库,视频+代码+资料
计算机后端-Java-Java核心基础-第21章 常用类 03. 复习:线程通信和新的线程创建方式
黑马程序员_张孝祥_Java多线程与并发库,老师讲的非常仔细,老师很有耐心.欢迎大家下载学习.
Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-优先级 Java线程:线程的调度-让步 Java线程:线程的调度-合并 Java线程:线程的调度-守护线程 Java线程:线程的...
Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-优先级 Java线程:线程的调度-让步 Java线程:线程的调度-合并 Java线程:线程的调度-守护线程 Java线程:...
计算机后端-Java-Java核心基础-第20章 多线程 02. 复习:IDEA使用与多线程基本概念.avi
计算机后端-Java-Java核心基础-第20章 多线程 15. 线程通信的例题.avi
计算机后端-Java-Java核心基础-第20章 多线程 03. 复习:线程的创建与常用方法.avi
计算机后端-Java-Java核心基础-第20章 多线程 17. 线程通信:生产者消费者例题.avi
Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-优先级 Java线程:线程的调度-让步 Java线程:线程的调度-合并 Java线程:线程的调度-守护线程 Java线程:线程的...
基于java的开发源码-超简单Java多线程填表源码.zip 基于java的开发源码-超简单Java多线程填表源码.zip 基于java的开发源码-超简单Java多线程填表源码.zip 基于java的开发源码-超简单Java多线程填表源码.zip 基于java...
多线程注意:wait()方法的调用要有判定条件常用 while () obj.wait(timeout, nanos); ... // Perform action appropriate to condition } synchronized会影响共享数据,但对其他语句的执行不会有规律了!