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

JAVA并发编程实战 ——线程安全性

2016-12-19 23:04 295 查看
以前也算是看过并发编程实战这本书。但是一直做的是书中的笔记。如今从头看此书。希望把笔记记录成博客。以便以后查询。

怎么确定一个类是线程安全的:

当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要添加额外的同步或者协同。这个类都能表现出正确的行为,那么就称这个类是线程安全的。

2.2.1:无状态对象一定是线程安全的

在本书中描述是:既不包含任何域,也不包含任何对其它类中域的引用。

在没有同步的情况下统计已处理请求数量的Servlet(不要这么做)

public class UnsafeCountingFactorizer  implements  Servlet {
private long count = 0;

public long getCount() {
return count;
}

@Override
public void service(ServletRequest request, ServletResponse response){
BigInteger  i = extraactFromeRequest(request);
BigInteger[]  factors = factor(i);
++count;
encodeIntoResponse(response, factors);

}
}


UnsafeContingFactorizer是非线程安全的。当多个线程访问时候,count在进行++count时,就会产生:竞态条件。 ++count在JVM中他的执行过程是 读取-修改-写入。多个线程对count进行++操作时候,就可能会产生多个线程读取的是同一个值,修改后的值一直,导致统计不准确。

2.2.2

延迟初始化中的竟态条件:

最常见的就是我们在单例模式中,我们可以采取延迟初始化而避免线程不安全。当然下面代码是线程不安全的。是一个错误示例:

//这个是线程不安全的。只是示例延迟初始化也会产生竟态条件
public class LazyInitRace {

private  LazyInitRace  lazyInitRace  ;
private LazyInitRace(){};

public LazyInitRace getInstance() {
if(lazyInitRace == null) {
lazyInitRace = new LazyInitRace();
}
return  lazyInitRace;
}

}


2.2.3 复合操作

包含一组必须以原子方式执行的操作我们称之为符合操作。如:延迟初始化、读取-修改-写入。

我们有时候可以采取原子变量类。java.util.concurrent.atomic中的原子变量类来保证线程安全性

public class UnsafeCountingFactorizer  implements  Servlet {
private final AtomicLong  count = new AtomicLong(0);

public long getCount() {
return count.get();
}

@Override
public void service(ServletRequest request, ServletResponse response){
BigInteger  i = extraactFromeRequest(request);
BigInteger[]  factors = factor(i);
count.incrementAndGet();
encodeIntoResponse(response, factors);

}
}


这样就可以解决线程安全性问题。当然对于java.utilconcurrent包下面的类会在后续读到的时候进行想写的记录。也会对源码进行分析记录。

2.3 锁

2.3.1:Java提供了一种内置的锁机制来支持原子性——同步代码块(Synchronized Block).被Synchronized 修饰的普通方法的锁就是方法调用所在的对象。简单讲就是对象锁。静态的Synchronized方法是一Class对象作为锁。也就是类锁。Java的内置锁是一种互斥锁:也就是说最多只有一个线程能持有这种锁。

2.3.2:重入:java内置锁是可以重入的。如果某个线程试图获取自己已经拥有的锁,那么这个请求就会成功。 “重入” 意味着获取锁的操作粒度是线程,而不是调用。

//内置锁可重入,就不会让这样的代码发生死锁。
public class Widget {
public synchronized void doSomething() {
...........
}
public class loggingWidget extends doSomething() {
public synchronized void doSomething() {
...........
super.doSomethin();
}

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线程安全 线程