【同步代码块】
* *在【a】手动添加休眠10毫秒,
*通过分析发现 打印出了0 -1 -2 等错票
*多线程的运行出现了安全无问题。
*问题的原因:
* 当多条语句在操作同一个线程共享数据时,一个线程对多个语句只执行流量一部分,
* 还没有执行完,另一个线程参与进来执行,导致共享数据的错误
*
*解决办法就是,
* 对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他现在不可以参与执行
*
*java对多线程的安全问题,提供了专业的解决方式
*
*就是【同步代码块】:
*
*sychronized(对象){
* 需要被同步的代码
*}
*
*对象如同锁,持有锁的线程可以在同步中执行。
*没有持有锁的线程即使获取到cpu的执行权,也进不去,因为没有获取锁。
*
*火车上的卫生间- - 经典解释锁的例子。
*
*
*同步的【前提】:
*1、必须要有2个或者2个以上的线程
*2、必须是多个线程使用同一个锁
*
*必须保证同步中只能一个线程在运行
*
*【好处】:解决了多线程的安全问题
*
*【弊端】:多个线程都需要判断锁,较为消耗资源。
*/
class Ticket1 implements Runnable{//方式二
private int tick=100;
Object obj=new Object();
public void run(){
while(true){
synchronized(obj){//obj 就相当于锁。
if(tick>0){
try{
Thread.sleep(10);//【a】
}
catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"买票"+(tick--));
}
}
}
}
}
public class D_Th_test3 {
public static void main(String[] args) {
Ticket t=new Ticket();//这只是创建对象
Thread t1=new Thread(t);
Thread t2=new Thread(t);
Thread t3=new Thread(t);
t1.start();
t2.start();
t3.start();
/*把Runnable 子类对象当作参数传递给Thread方法的构造函数,
* 通过调用Thread类的start方法开启线程并调用Runnable中的run方法
*/
}
}
-----------------------------------------------------------------------------------------------------------
/*sychronized 练习
* 需求:
* 银行有一个金库
* 有两个储户,分别存300,每次100 存3次。
*
* 目的:该程序是否有安全问题,如果有,如何解决。】
*
* 如何找到问题
* 1、明确那些代码是多线程代码
* 2、明确共享数据
* 3、明确多线程中那些语句是操作共享数据的
*
* 【同步有2种表现形式】:
* 1、同步代码块 synchronized(对象){}
* 2、同步函数[b]
*
* 下列:【test2】
* 返回去看刚刚test2卖票的小案例,他能使用同步函数吗,
* 答案是否定的,因为while是不需要同步的,锁到一起后,会出现一直循环打印的现象。
* 我们知道 synchronized中的锁是对象的,下来中的对象是谁?我们知道,show()前面减省了this,应该是 this.show();
* 那么这个锁就是this的。【明天继续,实在是困了。】
*
* 同步函数,到底用的是那一个锁
* 【非静态同步函数用的锁,是this】
*
* 通过该程序来卖票
* 使用两个线程来卖票
* 一个线程在同步代码块中,
* 一个线程在同步函数中,
* 都在执行卖票动作。
*
* 下列代码运行观察,有一定几率打印出0号票,
* 我们把run方法中传入的obj锁改为this,我们在试试
* 更改后,多次运行均无0出现
*
* 所以,推理得出同步函数使用的锁是this
*
*
*
*/
//[b] 同步函数
class Ticket4 implements Runnable{//方式二
private int tick=100;
Object obj=new Object();
boolean flag=true;
public void run(){
if(flag){
while(true){
//synchronized(obj){//obj 就相当于锁。
synchronized(this){//更换为this
if(tick>0){
try{
Thread.sleep(10);//【a】
}
catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"买票"+(tick--));
}
}
}
}
else{
while(true)
show();
}
}
public synchronized void show(){
if(tick>0){
try{
Thread.sleep(10);//【a】
}
catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"买票"+(tick--));
}
}
}
public class D_Th_test5 {
public static void main(String[] args) {
Ticket4 t=new Ticket4();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
t1.start();
try{
Thread.sleep(10);//【a】
}
catch(Exception e){}
t.flag=false;
t2.start();
}
}
---------- android培训、 java培训 、期待与您交流!----------
黑马官网: http://edu.csdn.net/heima