看编程思想一书,也写了段代码,发现对static的资源加锁无效,左思右想终于找出了原因,现贴出与大家分享。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class Source
{
int i=0;
}
class Generator
{
public static Integer i=0;
public static Source source=new Source();
public static Boolean isCancelled=false;
public int next()
{
/**
* 无效的资源加锁
*/
synchronized(i)
{
i++;
Thread.yield();
i++;
return i;
}
/**
* 有效的资源加锁
*/
// synchronized(source)
// {
// source.i++;
// Thread.yield();
// source.i++;
// return source.i;
// }
}
}
class Increase implements Runnable
{
int id;
Generator gen;
public Increase(Generator gen,int id)
{
this.gen=gen;
this.id=id;
}
@Override
public void run() {
while(gen.isCancelled==false)
{
int val=gen.next();
if(val%2!=0)
{
gen.isCancelled=true;
print("#"+id+" error. val="+val);
}
}
print("#"+id+" complete. gen:"+gen.next());
// print("#"+id+" complete. gen.i:"+gen.i.);
}
public static void print(Object obj)
{
System.out.println(obj);
}
}
public class TestLock
{
static ExecutorService exec = Executors.newCachedThreadPool();
public static void main(String[] args){
ExecutorService exec = Executors.newCachedThreadPool();
Generator gen=new Generator();
for(int i = 0; i < 10; i++)
exec.execute(new Increase(new Generator(), i));
exec.shutdown();
}
}
资源加锁的关键是确定所加锁的资源是否是唯一的,是否的分配的唯一内存地址的资源;
上面的无效加锁原因是:static对基本型i 并没有分配内存,而对于封装了的资源source
则用new关键字进行了初始化,并拥有唯一内存,因此对source的加锁才是对单一资源的加锁;
而对于资源i ,10个线程有10个i到底是对谁加锁呢?等于是没有加锁。
(有不恰当处,欢迎吐槽!!!)