黑马程序员——学习日记3

多线程——同步代码块、同步函数、静态同步函数

------ Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
线程安全问题解决思路:
就是将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,
其他线程是不可以参与运算的。
必须要当前线程把这些代码都执行完毕后,其他线程才可以参与运算。

同步代码块
在Java中,用同步代码块就可以解决这个问题。


同步代码块(同步锁)的格式:
synchronized(对象){
需要被同步的代码;
}
锁可以是任意对象。
示例:
class Ticket implements Runnable{
	private int num=100;
	Object obj=new Object();
	public void run(){
		while(true){
			<span style="color:#ff9900;">synchronized(obj)</span>{
				if(num>0){
					try{
						Thread.sleep(10);
					}
					catch(InterruptedException e){
						System.out.println("中断异常");
					}
					System.out.println(Thread.currentThread().getName()+"......sale......"+num--);
				}
			}
		}
	}
}
public class Ti{
	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);
		Thread t4=new Thread(t);
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}
示例里开启了四个线程,同时执行同一个任务代码,这样就很容易出现线程安全问题,比如这里卖出0号票的情况,所以我们给任务代码加上同步锁,使得一个线程在执行任务代码时,其他线程处于临时阻塞状态,就不会进入任务代码执行了。这样就保证了线程安全。


同步的好处:解决了线程的安全问题。

同步的弊端:相对降低了效率,因为同步外的线程都会判断同步锁。

同步的前提:同步中必须有多个线程并使用同一把锁

下面的代码虽然用了同步代码块,但是将创建锁对象放在了run方法里面,也就是说每个线程进来都new了一个锁对象,每个线程都拥有了各自不同的锁,这样同步代码块就没有起到应有的作用,仍然会出现卖0号票的情况,相当于没有锁。
class Ticket implements Runnable{
	private int num=100;
	public void run(){
	Object obj=new Object();
		while(true){
			synchronized(obj){
				if(num>0){
					try{
						Thread.sleep(10);
					}
					catch(InterruptedException e){
						System.out.println("中断异常");
					}
					System.out.println(Thread.currentThread().getName()+"......sale......"+num--);
				}
			}
		}
	}
}
public class Yi{
	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);
		Thread t4=new Thread(t);
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}
卖出了0、-1、-2号票。

同步函数:就是给方法加上synchronized。
锁是this。
示例:
class Bank{
	private int sum;
	<span style="color:#ff6600;">public synchronized void add(int num)</span>{//同步函数
		sum=sum+num;
		try{
			Thread.sleep(10);
		}
		catch(InterruptedException e){
			System.out.println("中断异常");
		}
		System.out.println("sum="+sum);
	}
}
class Cus implements Runnable{
	private Bank b=new Bank();
	public void run(){
		for(int x=0;x<3;x++){
			b.add(100);
		}
	}
}
public class Ni{
	public static void main(String[] args){
		Cus c=new Cus();
		Thread t=new Thread(c);
		Thread t1=new Thread(c);
		t.start();
		t1.start();
	}
}
运行结果如下图


同步代码块和同步函数的区别:
同步代码块的锁是任意对象。
同步函数的锁是固定的this。

建议使用同步代码块。同步函数就是同步代码块在锁为this时的偷懒简写。

静态同步函数:就是在静态函数上加上synchronized。
锁是该函数所属字节码文件对象。可以用getClass方法获取,也可以用 当前类名.class 表示。
示例:
class Ticket implements Runnable{
	private static int num=100;
	boolean flag=true;
	public void run(){
		if(flag){
			while(true){
				synchronized(Ticket.class){  //synchronized(this.getClass()){
					if(num>0){
						try{
							Thread.sleep(10);
						}
						catch(InterruptedException e){
							System.out.println("中断异常");
						}
						System.out.println(Thread.currentThread().getName()+"......obj......"+num--);
					}
				}
			}
		}else{
			while(true){
				this.show();
			}
		}
	}
	<span style="color:#ff6600;">public static synchronized void show()</span>{ //静态同步函数
		if(num>0){
			try{
				Thread.sleep(10);
			}
			catch(InterruptedException e){
				System.out.println("中断异常");
			}
			System.out.println(Thread.currentThread().getName()+"......function......"+num--);
		}
	}
}
public class Ji{
	public static void main(String[] args){
		Ticket t=new Ticket();
		Thread t1=new Thread(t);
		Thread t2=new Thread(t);
		t1.start();
		try{
			Thread.sleep(10);
		}
		catch(InterruptedException e){
			System.out.println("中断异常");
		}
		t.flag=false;
		t2.start();
	}
}
运行结果如下图


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值