class Synchronized implements Runnable
{
private boolean flag;
Synchronized (boolean flag)
{
this.flag=flag;
}
public void run()
{
if (flag==true)
{
synchronized(LockDemo.a)
{
System.out.println("a锁第一层");
synchronized(LockDemo.b)
{
System.out.println("a锁第二层");
}
}
}
else
synchronized(LockDemo.b)
{
System.out.println("b锁第一层");
synchronized(LockDemo.a)
{
System.out.println("b锁第二层");
}
}
}
}
class LockDemo
{
static LockDemo a=new LockDemo();
static LockDemo b=new LockDemo();
}
class LockDemo1
{
public static void main(String[] args)
{
Synchronized s=new Synchronized(true);
Synchronized s1=new Synchronized(false);
Thread t=new Thread(s);
Thread t1=new Thread(s1);
t.start();
t1.start();
}
}
我觉得s和s1不是2个对象么?那么线程t操作s对象 线程t1操作s1对象 两个线程操作的是两个不同对象它们两个怎么会有影响呢?
static LockDemo a=new LockDemo();
static LockDemo b=new LockDemo();其中一个是用:
synchronized(LockDemo.a) {
System.out.println("a锁第一层");
synchronized(LockDemo.b)
这种方式先锁住a,再锁住b。
而另一个使用:
synchronized(LockDemo.b) {
System.out.println("b锁第一层");
synchronized(LockDemo.a)
这种方式先锁住b,在锁住a。
所以就死锁了。
s、s1两个小朋友,a、b两个水果。s抢了a,还要b;s1抢了b,还要a。
线程t1操作s1对象,s1对象操作了 b 和 a;他们之间的联系是建立在:ab 上的。
这是一个亲子游乐场,举行抢水果比赛,于是:
母亲t,要求她的小孩s,去抢得两个水果a和b;
母亲t1,要求她的小孩s1,去抢得两个水果a和b;结果s先抢到了a,s1先抢到了b;但这都不算赢,所以他们死守住自己水果的同时,要拼命去抢对方的水果
Synchronized s1=new Synchronized(false);不是两个new么?我理解成2个游乐场,游乐场一。内母亲t要求小孩s去抢 游乐场二。母亲t1要求小孩抢感觉没什么关系啊。是哪一步理解错了?
class LockDemo {
static LockDemo a=new LockDemo();
static LockDemo b=new LockDemo();
}
不是你说的:
Synchronized s=new Synchronized(true);
Synchronized s1=new Synchronized(false);
这两个只是执行者,是(Runnable):
class Synchronized implements Runnable {
无非可能是名字叫Synchronized显得比较不好,跟同步关键字长得很像,所以容易引起误会,建议把这个类的名字改为:Worker之类的。
真正执行了“抢占”动作的语句是:
synchronized(LockDemo.a) 和 synchronized(LockDemo.b)
游乐场2内 小孩s1抢了b还想抢a
而a 和b是两个游乐场公有的。
不知道是不是可以这么理解?
如果不是同一个游乐场 为啥还要new 2个
Synchronized s=new Synchronized(true);
Synchronized s1=new Synchronized(false);
该问题也是一样的。
new了两只筷子a,b。new了两个人s,s1.
规则是 拿到两个锁之后就可以线程结束释放锁,就是拿到两种筷子吃完饭,筷子洗一下别人又可以用了。
结果s拿着a筷子不放,b拿着b筷子不放,结果两个人都吃不了饭,资源释放不了,产生死锁。
{
/*static*/ LockDemo b=new LockDemo();
/*static*/ LockDemo a=new LockDemo();
private boolean flag;
Person (boolean flag)
{
this.flag=flag;
}
public void run()
{
if (flag==true)
{
synchronized(LockDemo.a)
{
System.out.println("a锁第一层");
synchronized(LockDemo.b)
{
System.out.println("a锁第二层");
}
}
}
else
synchronized(LockDemo.b)
{
System.out.println("b锁第一层");
synchronized(LockDemo.a)
{
System.out.println("b锁第二层");
}
}
}
}class LockDemo1
{
public static void main(String[] args)
{
Person s=new Person(true);
Person s1=new Person(false);
Thread t=new Thread(s);
Thread t1=new Thread(s1);
t.start();
t1.start();
}
}
我想应该这么问 , 就是以上程序注释部分的static 写着后再运行和不写后再运行结果的区别在哪里,为什么会造成这样的区别。(感觉有点老师在质问学生的感觉,小弟初学者,表达能力也不好望各位大哥谅解)。
class Synchronized implements Runnable
它实现了接口Runnable,从这个语义上来说,它只能是个执行者,有主观能动性才行。游乐场有主观能动性么?
public void run()函数就是它的主要动作内容,或者说执行内容。3、被抢的是资源,资源受环境所管辖,且自身也不具备主观能动性,在这个理解下:
static LockDemo a=new LockDemo();
static LockDemo b=new LockDemo();
是符合该特性的。4、Thread t=new Thread(s); 那这是啥?
只能理解为许可性的内容,其start()相当于让Runnable这个执行者开始执行其动作。
那么可以理解为:进游乐场玩抢资源的门票 或者 母亲的命令。
static LockDemo a = new LockDemo();
static LockDemo b = new LockDemo();
改成
LockDemo a = new LockDemo();
LockDemo b = new LockDemo();
就和你一开始想的一样。如果是
static LockDemo a = new LockDemo();
static LockDemo b = new LockDemo();
你那样理解是错的去了解下static
这么改后,这程序就没法编译了:
synchronized(LockDemo.a)
只能对静态成员这样引用。另外,楼主同学,我5楼说了:
你要注意他们抢的都是LockDemo中的static成员:a 和 b,这是全JVM唯一的:
class LockDemo {
static LockDemo a=new LockDemo();
static LockDemo b=new LockDemo();
}
{
/*static*/ LockDemo b=new LockDemo();
/*static*/ LockDemo a=new LockDemo();
private boolean flag;
Person (boolean flag)
{
this.flag=flag;
}
public void run()
{
if (flag==true)
{
synchronized(LockDemo.a)
{
System.out.println("a锁第一层");
synchronized(LockDemo.b)
{
System.out.println("a锁第二层");
}
}
}
else
synchronized(LockDemo.b)
{
System.out.println("b锁第一层");
synchronized(LockDemo.a)
{
System.out.println("b锁第二层");
}
}
}
}
class LockDemo1
{
public static void main(String[] args)
{
Person s=new Person(true);
Person s1=new Person(false);
Thread t=new Thread(s);
Thread t1=new Thread(s1);
t.start();
t1.start();
}
}
我指的是这个程序里跟上面那个不一样,改过了。
/*static*/ LockDemo b=new LockDemo();
/*static*/ LockDemo a=new LockDemo();
两个苹果(对象级的成员变量)。既然不存在对同一个资源的竞争,当然相互之间就完全没任何关系,当然不可能死锁。
根本都不需要写类名:
synchronized(LockDemo.a)
你直接这么写就行了:
synchronized(a);
或者:
synchronized(b);
static代表该变量为类静态变量,是该类所生成的所有对象所共享的。
static LockDemo a = new LockDemo();
static LockDemo b = new LockDemo();
存在于方法区中并不是每一个对象里都有的,这是全JVM唯一的:
synchronized(LockDemo.a)
{
System.out.println("a锁第一层");
synchronized(LockDemo.b)
{
System.out.println("a锁第二层");
}
}
所以当s操作到这个第二层时需要方法区中b的锁但是此时b锁是锁着的
synchronized(LockDemo.b)
{
System.out.println("b锁第一层");
synchronized(LockDemo.a)
{
System.out.println("b锁第二层");
}
}
当s1操作到这个第二层时需要方法区中a的锁 但此时a锁是锁着的