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()的时候将无法执行。



如果可以重入的话,这个doSometing函数的锁已经被线程所持有,所以它可以获得所有doSomething的锁,就不会陷入“死锁”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值