您的位置:首页 > 编程语言 > Java开发

JAVA多线程单例模式及死锁

2012-11-22 10:07 387 查看
上一篇我总结了创建多线程的两种方式(继承Thread类与实现Runnable接口),及多线程的不安全性,及解决多线程不安全的两种方式(同步代码块和同步函数)。

现在开始总结多线程的几种状态。



1 上图为线程运行的五种状态

线程被start()后,不一定马上运行,有可能进入阻塞状态,因为当前时间段CPU有可能正在运行其他线程。

Sleep()/wait()为冻结操作,线程会没有CPU的执行权。

Sleep()时间到后,会自动激活。

Notify()为唤醒线程。

就绪:具备运行资格,但没有执行权(等待CPU的执行权)

阻塞:放弃了执行资格,处于暂停状态

再来回顾一下进程中的概念,进程中有挂起,而线程中没有,进程也具备以上5中状态。

活动就绪:进程处于未被挂起的就绪状态

活动阻塞:进程处于未被挂起的阻塞状态

上面两个概念是将5种状态增加到7种状态后的称呼,此外还有静止就绪和活动就绪。

2 同步函数的锁是this
函数需要被对象调用,函数都有一个所属对象的引用,就是this,所以同步函数使用的锁是this.

3 静态同步函数的锁是Class对象
函数可以加static关键字
静态方法进内存的时候没有对象,静态对象由类调用,类进内存的时候会自动生成字节码文件对象class

4 单例设计模式

/*
*	饿汉式
*/
class Single
{
private static final Single s = new Single();

private Single()
{
}

public static Single getInstance()
{
return s;
}
}


/*
*  懒汉式
*/
class Single2
{
private static Single2 s = null;

private Single2()
{
}

public static Single2 getInstance()
{
if (s == null)
{
s = new Single2();
}
return s;
}
}


针对懒汉式进行分析,发现在多线程情况下,懒汉式会发生线程不安全。

有可能出现多个线程同时进入getInstance()语句,从而生成多个实例,达不到单例的效果。

针对这种情况可以讲方法更改为同步函数,但是因为每次都要判断锁,会影响效率,最后对懒汉式的代码做如下修改:

class Single2
{
private static Single2 s = null;

private Single2()
{
}

public static Single2 getInstance()
{
if (s == null)
{
synchronized (Single2.class)
{
if(s == null)
{
s = new Single2();
}
}

}
return s;
}
}


写同步代码块,通过双重判断的形式

这样做的好处就是减少了判断锁的动作,相对提高了性能。

5 死锁
是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
死锁代码示例:

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

public void run()
{
if (flag)
{
while (true)
{
synchronized (MyLock.locka)
{
System.out.println("if__a");
synchronized (MyLock.lockb)
{
System.out.println("if__b");
}
}
}
}
else
{
while (true)
{
synchronized (MyLock.lockb)
{
System.out.println("else__b");
synchronized (MyLock.locka)
{
System.out.println("else__a");
}
}
}
}
}
}

class MyLock
{
static Object locka = new Object();
static Object lockb = new Object();
}

public class Test6
{
public static void main(String[] args)
{
Test t1=new Test(true);
Test t2=new Test(false);
Thread c1=new Thread(t1);
Thread c2=new Thread(t2);
c1.start();
c2.start();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐