一、单例设计模式(懒汉式)中的线程不安全问题
看之前写过的一个单例
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();
}
}
}