一、單例設計模式(懶漢式)中的線程不安全問題
看之前寫過的一個單例
public class SingleTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Single s1 = Single.getInstance();
Single s2 = Single.getInstance();
System.out.println(s1==s2);
}
}
class Single{
private Single() {
}
private static Single s = null;
public static Single getInstance(){
if(s==null){
s = new Single();
}
return s;
}
}
在多線程情況下,上面的單例會出現多次判斷的問題。如果直接在getInstance()方法前面加上synchronized 則執行效率會比較低,沒創建一次,都得判斷是否lock住。可以加上雙重判斷,來減少鎖的判斷次數。同步鎖是該類所屬的字節碼文件對象。
class Single {
private Single() {
}
private static Single s = null;
public static Single getInstance() {
if (s == null) {
synchronized (Single.class) {
if (s == null) {
s = new Single();
}
}
}
return s;
}
}
二、進程同步問題
問題描述:設有兩個線程,一個線程負責寫數據(前後兩次數據不同,可以設置flag變量來進行input的切換),另一個線程負責讀數據。問如何實現同步。
public class InputOutput {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Resource r = new Resource();
Input in = new Input(r);
Output out = new Output(r);
Thread thread = new Thread(in);
Thread thread1 = new Thread(out);
thread.start();
thread1.start();
}
}
class Resource{
String name ;
String sex ;
}
class Input implements Runnable{
Resource s;
Input(Resource s){
this.s= s;
}
public void run(){
boolean flag = true;
while(true){
synchronized(s){
if(flag){
s.name = "張三";
s.sex = "男";
flag = false;
}else{
s.name = "麗麗";
s.sex = "女";
flag = true;
}}
}
}
}
class Output implements Runnable{
Resource s;
Output(Resource s){
this.s = s;
}
public void run(){
while(true){
synchronized(s){
System.out.println(s.name+" "+s.sex);}
}}
}
代碼優化後:
public class InputOutput {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Resource r = new Resource();
Input in = new Input(r);
Output out = new Output(r);
Thread thread = new Thread(in);
Thread thread1 = new Thread(out);
thread.start();
thread1.start();
}
}
class Resource {
private String name;
private String sex;
private boolean flag;
public synchronized void set(String name, String sex) {
if (!flag) {
this.name = name;
this.sex = sex;
flag = true;
this.notify();
}
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public synchronized void info() {
if (flag) {
System.out.println(name + "..." + sex);
flag = false;
this.notify();
}
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Input implements Runnable {
Resource s;
Input(Resource s) {
this.s = s;
}
public void run() {
boolean flag = true;
while (true) {
if (flag) {
s.set("張三", "男");
flag = false;
} else {
s.set("麗麗", "女");
flag = true;
}
}
}
}
class Output implements Runnable {
Resource s;
Output(Resource s) {
this.s = s;
}
public void run() {
while (true) {
s.info();
}
}
}