多线程__【线程安全】【线程同步】【单例模式的线程安全】【线程死锁】

原创 2013年12月06日 16:37:10



线程安全问题

线程安全问题产生的原因:多条线程代码操作共享数据一条线程还未执行完,并对结果进行反馈;其他的线程通过条件判断参与进运算,对数据重复操作

多次启动一个线程是非法的,尤其是线程已经结束后,不能重新启动

买票示例

/*卖票示例

*/
class Ticket implements Runnable
{
	private int num = 100;

	public void sale()
	{
		while (true)//
		{
			if (num>0)
			{
				try//使用sleep方法时会出现异常,继承的接口没有继承Exception 异常,所以run方法不能throws,只能try catch
				{
					Thread.sleep(10);//线程休眠10毫秒
				}
				catch (InterruptedException e)
				{
				}
				System.out.println("name: "+Thread.currentThread().getName()+"....."+num--);
			}
		}
	}
	public void run()
	{
		sale();
	}
}

class  TicketDemo
{
	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();
	}
}

运行结果出现负数票



解决方法:

当前线程执行完毕后,其它线程才能参与运算。

将共享数据的代码封装起来,当有线程在执行这些代码的时候。其它线程不可以参与运算,使用


线程同步

class Ticket implements Runnable
{
	private int num = 100;
	Object obj =new Object();

	public synchronized void sale()//同步函数,不能直接调用,因为一个线程进入后全部执行完才出来,其它线程没有锁所以执行不到
	{
		while (true)
		{
		//	synchronized(obj)//同步代码块,同步锁;需要传入对象,可以是任意对象,作为自定义锁
		//	{
				if (num>0)
				{
					try
					{
						Thread.sleep(10);//线程休眠10毫秒
					}
					catch (InterruptedException e)
					{
					}
					System.out.println("name: "+Thread.currentThread().getName()+"....."+num--);
				}
		//	}	
		}
	}
	public void run()//所有线程都可以调用run方法,在run方法中间接调用同步函数,从而间接执行到sale();
	{
		sale();
	}
}


对象如同同步就相当于一个保险箱,持有锁的线程可以进入同步中执行,没有锁的线程即使获取cpu执行权,也无法进去执行

经典实例----火车上的卫生间

同步的前提多个线程使用同一个锁,必须保证同步中只有一个线程在执行

同步的弊端多个线程需要判断锁,较为消耗资源

同步的原则明确哪些代码是多线程运行代码;明确共享数据;明确多线程运行代码哪些是操作共享数据的,只能有一个共同的


同步的方式

同步代码块

synchronized(对象){需要被同步的代码}//只需要把需要同步的代码封装在同步中,同步代码块的锁是传入的对象,可以是任意对象,自定义锁。

同步函数

同步函数的锁:函数需要被对象调用,那么函数都有一个所属对象的引用,就是this。即当前任务对象

(考点)静态同步函数使用的锁是该方法所在类的字节码文件对象,类名.class

静态成员进内存的过程:内存中没有本类对象,但是一定有该类对应的字节码文件对象,类名.class,该对象的类型是class

总结:同步函数中,那个对象调用了同步,同步锁就是该对象的引用


单例模式的线程安全问题

懒汉式特点:对象延迟加载,多线程访问时存在安全隐患;可以加同步来解决。同步过程中判断锁会降低效率,而同步函数每一条线程访问都会有判断锁的过程;使用同步代码块二次判断,用判断变量来替代判断锁,只需判断一次锁,稍微提高了执行效率

由于是静态同步,所以懒汉式中的同步锁是本类对象的字节码文件


//饿汉式
class Single
{
	private static final Single s=new Single();//有final修饰
	private Single(){}
	public static Single getInstance()
	{
		return s;
	}
}

//懒汉式
class Single
{
	private static Single s =null;//无final修饰
	private Single(){}

//	public static Single getInstance()//延迟加载,多个线程并发访问时可能引发安全问题
//	public static synchronized Single getInstance()使用同步函数,多了一步判断锁的过程,多线程时较为低效
	public static Single getInstance()	//使用同步代码块
	{
		if (s==null)//减少判断锁的次数,稍微提高效率
		{
			synchronized(Single.class)//静态同步的锁
			{
				if(s==null)
					s=new Single();	
			}
				return s;
		}
	}
}

线程死锁

死锁的条件:同步中嵌套同步,同步之间的调用,由于每个同步只有一个对应的锁,相互嵌套时同时持有两个锁才会执行,一旦两个同步都持有一个对方的锁无法执行也无法释放,就会导致线程死锁。这种情况应避免发生

死锁示例:

class Test implements Runnable
{
	private boolean flag;
	Test(boolean flag)
	{
		this.flag = flag;
	}

	public void run()
	{
		if (flag)
		{
			synchronized(MyLock.a)
			{
				System.out.println("if.....a");
				synchronized(MyLock.b)
				{
					System.out.println("if....b");
				}
			}
		}
		else
		{
			synchronized(MyLock.b)
			{
				System.out.println("else....b");
				synchronized(MyLock.a)
				{
					System.out.println("else......a");
				}
			}
		}
	}
}

class MyLock
{
	static Object a= new Object();
	static Object b= new Object();
}

class DeadLock 
{
	public static void main(String[] args) 
	{
		Thread t1=new Thread(new Test(true));
		Thread t2=new Thread(new Test(false));
		t1.start();
		t2.start();
	}
}




相关文章推荐

Java--线程--线程控制,线程安全,线程同步,线程等待,线程交互,死锁,互斥锁,读写锁

多进程   每个进程间拥有独立的内存空间   0~4G  单核   系统将cpu所有时间分割为相同的时间片  由内核负责调度    线程属于进程内部  进程内部的所有线程共享进程的内存...
  • zlQQhs
  • zlQQhs
  • 2012年12月03日 20:38
  • 1692

设计模式——单例模式(Java)——考虑多线程环境下的线程安全问题

设计模式——单例模式(Java)——考虑多线程环境下的线程安全问题 一:单例模式概念 单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类...

JAVA-15-多线程的调度和控制、线程安全、死锁、等待和唤醒

本节我们开始讲解多线程: 1: 多线程的概念   (1)线程是依赖于进程而存在的。     A:进程 正在运行的应用程序     B:线程 进程的执行路径,执行单元      ...

线程安全的单例模式

  • 2012年12月07日 15:29
  • 345KB
  • 下载

c++线程安全单例模式

  • 2010年04月01日 16:08
  • 2KB
  • 下载

《多线程编程》学习之十:定时器Timer的使用,线程安全的单例模式

一、定时器Timer的使用          定时器 Timer类主要的作用是设置计划任务,它在内部使用多线程的方式进行处理;而抽象的TimerTask类负责封装任务,它实现了Runnable接口。 ...

JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制

JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是cl...

Java多线程之线程安全与同步实例

1.1    线程安全与同步实例 1.1.1  购票同步对象锁 【 /*  * 用程序模拟铁路售票系统:实现通过两个售票点发售某日某次列车的50张车票,  * 一个售票点用一个线程表示  ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:多线程__【线程安全】【线程同步】【单例模式的线程安全】【线程死锁】
举报原因:
原因补充:

(最多只允许输入30个字)