0
点赞
收藏
分享

微信扫一扫

1线程安全


1线程安全的定义

当多个线程访问某个类时,这个类始终都能表现出正确的行为,那么就称这个类是线程安全的。

2.两种状态

(1)状态

对象的状态是指存储在状态变量(例如实例和静态域)中的数据。

【举例】

Person p=new Person(Li);
p.age=12;

对象Li今年12岁,这是对象Li存于的一个状态

(2)共享状态

“共享”意味着变量可以由多个线程同时访问

(3)可变状态

“可变”则意味变量的值在其生命周期内方式变化

【举例】

两个线程进行计数

T1()

{count++;

}

T2()

{count++;

}


两个线程都访问count,所以count是共享变量,都执行count++操作,所以count是可变变量。

3.竞态条件

在并发编程中,由于恰当的执行时序而出现不正确结果的情况,叫做竞态条件。

【举例】

例1“读取—修改—写入”

Static int count;

GetCount(int count)

{return count;

}

T1()

{count=GetCount();

count++;

}

T2()

{count=GetCount();

count++;

}

这样会出现竞态条件。

初始count=0;

(1) T1获取CPU,执行GetCount(),count=0;

(2) T2获取CPU,执行GetCount(),count=0;

(3) T1获取CPU,这行count++,返回,count=1;

(4) T2 获取CPU,执行count++,返回,count=1;

进行了两次计数,但是计数的值为1.

例2“延迟初始化”

T1()

{if(instance==null)

Instance=new Object();

Return instance;

}

T2()

{if(instance==null)

Instance=new Object();

Return instance;

}


这样也会出现竞态条件

初始instance=null;

(1) T1获取CPU,执行if(instance==null)

(2) T2获取CPU,执行if(instance==null)

(3) T1获取CPU,执行Instance=new Object();instance被实例化了

(4) T2获取CPU,执行Instance=new Object();instance又被实例化了

(5) T1获取CPU,返回intance,但是返回的是T2实例化的对象

这两个例子是比较典型的静态条件的例子。

4.如何保证线程的安全

4.1原子性

一组操作要么全都执行,要么全都不执行

4.2加锁操作

Lock{

保护的代码块。

}

保证了原子性,但是,性能比较低

4.3重入

当某个线程请求由其他线程所持有的锁的时候,发出请求的线程就会阻塞。但是,如果某个线程试图获得一个已经由它自己持有的锁,那么这个请求将会成功,这就是“重入”。

【举例】

Public class Widget{

Public lock void doSomething()

{

}

}

Public class LoggingWidget extends Widget(){

Public lock void doSometing(){

Super.doSomething();

}

}

如果不能重入的话,
LoggingWidget Lw=new LoggingWidget();
Lw.doSometing();//执行这条执行的时候,父类和子类中的doSometing都上锁了。当使用Super.doSomething()的时候将无法执行。

举报

相关推荐

0 条评论