- 可见性
在没有同步的情况下,共享变量(错误的做法):
1 | package net.jcip.examples; |
- volatile
同步的弱形式,仅仅可见,而且对它的操作不会与其他的内存操作一起被重排序,volatile变量不会缓存中寄存器或缓存在其他处理器隐藏的地方,所以读取一个volatile变量,总是会返回有某一个线程所写入的最新值,但是volatile不会阻塞。
一个很好的例子,数羊🐑:
1 | package net.jcip.examples; |
允许内部可变的数据溢出(不要这样做) :
1 | package net.jcip.examples; |
隐式的运行this溢出(不要这样做):
1 | package net.jcip.examples; |
栈限制:
package net.jcip.examples;
import java.util.*;
public class Animals {
Ark ark;
Species species;
Gender gender;
public int loadTheArk(Collection<Animal> candidates) {
SortedSet<Animal> animals;
int numPairs = 0;
Animal candidate = null;
// animals confined to method, don't let them escape!
animals = new TreeSet<Animal>(new SpeciesGenderComparator());
animals.addAll(candidates);
for (Animal a : animals) {
if (candidate == null || !candidate.isPotentialMate(a))
candidate = a;
else {
ark.load(new AnimalPair(candidate, a));
++numPairs;
candidate = null;
}
}
return numPairs;
}
class Animal {
Species species;
Gender gender;
public boolean isPotentialMate(Animal other) {
return species == other.species && gender != other.gender;
}
}
enum Species {
AARDVARK, BENGAL_TIGER, CARIBOU, DINGO, ELEPHANT, FROG, GNU, HYENA,
IGUANA, JAGUAR, KIWI, LEOPARD, MASTADON, NEWT, OCTOPUS,
PIRANHA, QUETZAL, RHINOCEROS, SALAMANDER, THREE_TOED_SLOTH,
UNICORN, VIPER, WEREWOLF, XANTHUS_HUMMINBIRD, YAK, ZEBRA
}
enum Gender {
MALE, FEMALE
}
class AnimalPair {
private final Animal one, two;
public AnimalPair(Animal one, Animal two) {
this.one = one;
this.two = two;
}
}
class SpeciesGenderComparator implements Comparator<Animal> {
public int compare(Animal one, Animal two) {
int speciesCompare = one.species.compareTo(two.species);
return (speciesCompare != 0)
? speciesCompare
: one.gender.compareTo(two.gender);
}
}
class Ark {
private final Set<AnimalPair> loadedAnimals = new HashSet<AnimalPair>();
public void load(AnimalPair pair) {
loadedAnimals.add(pair);
}
}
}
ThreadLocal:
package net.jcip.examples;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* ConnectionDispenser
* <p/>
* Using ThreadLocal to ensure thread confinement
*
* @author Brian Goetz and Tim Peierls
*/
public class ConnectionDispenser {
static String DB_URL = "jdbc:mysql://localhost/mydatabase";
private ThreadLocal<Connection> connectionHolder
= new ThreadLocal<Connection>() {
public Connection initialValue() {
try {
return DriverManager.getConnection(DB_URL);
} catch (SQLException e) {
throw new RuntimeException("Unable to acquire Connection, e");
}
};
};
public Connection getConnection() {
return connectionHolder.get();
}
}
- 不可变性
package net.jcip.examples;
import java.util.*;
import net.jcip.annotations.*;
public final class ThreeStooges {
private final Set<String> stooges = new HashSet<String>();
public ThreeStooges() {
stooges.add("Moe");
stooges.add("Larry");
stooges.add("Curly");
}
public boolean isStooge(String name) {
return stooges.contains(name);
}
public String getStoogeNames() {
List<String> stooges = new Vector<String>();
stooges.add("Moe");
stooges.add("Larry");
stooges.add("Curly");
return stooges.toString();
}
}
安全的发布对象:
1、 通过静态初始化器初始化对象的引用。
2、将它的引用存储到volatile域或AtomicReference。
3、将它的引用存储到正确创建的对象的final域中(创建期间没有发生 this 引用的溢出)。
4、将它的引用存储到由锁正确保护的域中。
线程安全容器内的同步,意味着将对象放入这些容器,就保证了安全。