多线程安全问题及代码的同步

多线程的出现,使得多个功能能够同时工作,但是也带来了问题。

实例说明:

class MyThread implements Runnable
{
	private int num=1;
	public void run()
	{
		if(num>0)
			System.out.println("num="+(num--));
	}
}
class Demo 
{
	public static void main(String[] args) 
	{
		MyThread t=new MyThread();
		Thread t1=new Thread(t);
		Thread t2=new Thread(t);//这里t1,t2公用一个对象t,所以t.num是t1,t2共享数据
		t1.start();
		t2.start();
	}
}
==============================================================================
分析:
如果线程1做完判断if(num>0)后就切换到线程2去做判断,在这过程中num并没有被处理过,
此时的num=1,那么就会输出1和0,0并不是我们希望的数据。
问题产生的原因:当多条语句在操作多线程共享数据时(比如例子中的num),若其中一个线程只执行了其中的一部分,cpu就切换到另一个线程去执行那些语句,这时就会产生共享数据的处理错误。

处理办法:引入同步代码块

格式:

synchronized(对象)

{

需要同步的代码(操作多线程共享数据的语句);

}

修改后的代码:

class MyThread implements Runnable
{
	private int num=1;
	Object obj=new Object();
	public void run()
	{
		synchronized(obj)//对象可以随意给。。
		{
			if(num>0)
			System.out.println("num="+(num--));
		}
	}
}
class Demo 
{
	public static void main(String[] args) 
	{
		MyThread t=new MyThread();
		Thread t1=new Thread(t);
		Thread t2=new Thread(t);//这里t1,t2公用一个对象t,所以t.num是t1,t2共享数据
		t1.start();
		t2.start();
	}
}
==============================================================================
效果:
执行同步代码块在被线程执行时,只有当一个线程把同步代码块中的语句全部执行完,其
他线程才能执行
同步代码块并不是越多越好,思考一下,如果整个run方法都同步,那么就相当于单线程。

需要同步的前提:

1,必须要有多个线程执行同步的代码。

2,同步的代码必须要有对线程共享数据的操作。

========================================================================================================

除了,同步代码块,还有一种同步的方法,那就是同步函数。

当需要同步的代码正好是一个函数时,只要用synchronized关键字去修饰该函数就能使得该函数具有同步的性质,即一个线程没有执行完该函数,其他线程就不能执行该函数。

上诉实例修改:

class MyThread implements Runnable
{
	private int num=1;
	public synchronized void run()
	{
			if(num>0)
			System.out.println("num="+(num--));
	}
}
class Demo 
{
	public static void main(String[] args) 
	{
		MyThread t=new MyThread();
		Thread t1=new Thread(t);
		Thread t2=new Thread(t);//这里t1,t2公用一个对象t,所以t.num是t1,t2共享数据
		t1.start();
		t2.start();
	}
}

不过同步函数也有局限性,就是他要求整个函数都需要同步时才使用,如果一个函数中只有其中一小部分代码需要同步,那应该优先选用同步代码块。

========================================================================================================================

如果共享数据被static修饰,那么同步代码块使用格式应该改为:synchronized(所在类类名.class)

========================================================================================================================

同步代码块中的对象参数相当于一把锁,每当有线程进入,“锁”就标记一次,出来时去掉标记,从而保证代码块中不会同时存在多个线程,因此,如果你想让多个同步代码块实现同步的效果,即多个同步代码块中不会同时存在多个线程,那么只要让这几个同步代码块传入同一个参数对象即可,而同步函数相当于一个参数对象为this的同步代码块。










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值