日期:2014-05-20  浏览次数:20688 次

阿里的一个面试题目:实现一个线程安全的类
今天被阿里面跪了,其中有一个问题我目前还没有想到答案,他们提出的问题是,不要用锁,不要用sychronized块或者方法,也不要直接使用jdk提供的线程安全的数据结构,需要自己实现一个类来保证多个线程同时读写这个类中的共享数据是线程安全的,怎么破?
线程安全 jdk 同步

------解决方案--------------------
我的思路:
在这个类中维护一个队列,用来记录要访问共享数据的线程。每次只能由队列头部所表示的线程访问这些数据,一旦这个线程访问完毕,就出队。
这是看Python官方文档得到的启示。
------解决方案--------------------
引用:
volatile boolean flag = true;

这样如何


public class Counter {
 
    public volatile static int count = 0;
 
    public static void inc() {
 
        //这里延迟1毫秒,使得结果明显
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
        }
 
        count++;
    }
 
    public static void main(String[] args) {
 
        //同时启动1000个线程,去进行i++计算,看看实际结果
 
        for (int i = 0; i < 1000; i++) {
            new Thread(new Runnable() {
               // @Override
                public void run() {
                    Counter.inc();
                }
            }).start();
        }
 
        //这里每次运行的值都有可能不同,可能为1000
        System.out.println("运行结果:Counter.count=" + Counter.count);
    }
}

------解决方案--------------------


class ThreadSafe{

private static int toSecond = 5*1000; //超时毫秒数
private  boolean flag = false;
private  int source = 1;

public int printSource(){
return source;
}


public boolean incSource(){
if (!canAccess()){
return false;
}
flag = true;
source++;
flag = false;
return true;
}


public boolean decSource(){
if (!canAccess()){
return false;
}
flag = true;
source--;
flag = false;
return true;
}

/**
 * 判断能不能访问,不能访问说明在修改,要等待一下
 */
private boolean canAccess(){
int time=0;
while (flag){
try{
Thread.sleep(2);
}catch(Exception ex){
//不考虑那么多,不做处理
}
time+=100;
//这里也不考虑那么多,认为循环一次就100毫秒
if (time>toSecond){
return false;
}
}
return true;
}

}


根据各位大牛的意见写个例子让大家喷喷。
------解决方案--------------------
引用:
Quote: 引用:

Quote: 引用:

Quote: 引用:

设置标记位。
访问方法先判断标记位是否为false,否的话改为true然后运行,运行完改回来。
大公司就喜欢这个,不需要你懂多少,但是希望你懂原理,具有创新性
弱弱的问一句用锁是怎么样的?怎么感觉就是这样?

这是典型的先询问后执行问题,多线程并发编程最忌这个,你这个设置标志位是行不通的。
你可以将这个共享变量设置为final域就可以了,它这个就是告诉你final域的重要性吧。
否则没有锁是不可想象的


final 域可以做到数据安全,能详细说说是怎么回事吗?我还是第一次听说。


jvm对final域会做特殊化处理,final域可以保证可见性,由于final域是不可变的,故而无需担心多线程并发导致的数据不一致问题,不过我还得补充一点,就是当final域为对象引用时,final域引用的对象是可变的时,仍然是非线程安全的,
我说的还是有点纠结,说白了就是把这个类设计为不可变类。不可变类绝对是线程安全的。