Vâng, nó là cần thiết. Có một số phương pháp bạn có thể sử dụng để đạt được sự an toàn của chuỗi với khởi tạo lười biếng:
Đồng bộ hóa hà khắc:
private static YourObject instance;
public static synchronized YourObject getInstance() {
if (instance == null) {
instance = new YourObject();
}
return instance;
}
Giải pháp này yêu cầu mọi luồng phải được đồng bộ trong khi thực tế chỉ cần một vài luồng đầu tiên.
Kiểm tra kỹ đồng bộ hóa :
private static final Object lock = new Object();
private static volatile YourObject instance;
public static YourObject getInstance() {
YourObject r = instance;
if (r == null) {
synchronized (lock) { // While we were waiting for the lock, another
r = instance; // thread may have instantiated the object.
if (r == null) {
r = new YourObject();
instance = r;
}
}
}
return r;
}
Giải pháp này đảm bảo rằng chỉ một số luồng đầu tiên cố gắng lấy được singleton của bạn phải trải qua quá trình lấy được khóa.
Khởi tạo theo yêu cầu :
private static class InstanceHolder {
private static final YourObject instance = new YourObject();
}
public static YourObject getInstance() {
return InstanceHolder.instance;
}
Giải pháp này tận dụng các đảm bảo của mô hình bộ nhớ Java về khởi tạo lớp để đảm bảo an toàn luồng. Mỗi lớp chỉ có thể được tải một lần và nó sẽ chỉ được tải khi cần thiết. Điều đó có nghĩa là lần đầu tiên getInstance
được gọi, InstanceHolder
sẽ được tải và instance
sẽ được tạo, và vì điều này được kiểm soát bởi ClassLoader
s nên không cần đồng bộ hóa bổ sung.