黑马程序员技术交流社区

标题: java线程同步于锁的问题 [打印本页]

作者: 黄敏    时间: 2012-8-9 14:38
标题: java线程同步于锁的问题
今天看了毕老师的java多线程教程,遇到一个问题就是想不明白了 求教!
问题 :  synchronized() 同步这个()理必须有对象,毕老师也说什么对线都行 随便写 ,这个对象就起到锁的功能,1,是谁给了这个对象 锁的功能呢?
2,这个对象是怎么判断一个线程进来了就改变这个对象标示位了?

3,一个线程走完同步代码块 ,又是怎么把标示位改变回去了呢?这其中是谁再操作这个对象了呢?


看底下的代码,帮忙解释清楚,现在还晕着呢

class Ticket implements Runnable
{
        private  int tick = 1000;
        Object obj = new Object();
        public void run()
        {
                while(true)
                {
                        synchronized(obj)
                        {
                                if(tick>0)
                                {
                                        //try{Thread.sleep(10);}catch(Exception e){}
                                        System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--);
                                }
                        }
                }
        }
}


class  TicketDemo2
{
        public static void main(String[] args)
        {

                Ticket t = new Ticket();

                Thread t1 = new Thread(t);
                Thread t2 = new Thread(t);
                Thread t3 = new Thread(t);
                Thread t4 = new Thread(t);
                t1.start();
                t2.start();
                t3.start();
                t4.start();


        }
}



作者: 黄敏    时间: 2012-8-9 14:48
这个问题没人能解决吗?
作者: 张_涛    时间: 2012-8-9 14:53
速来回答,有分奖!
作者: pphdsny3    时间: 2012-8-9 15:03
这是java虚拟机的运行机制,也是java这门语言的规则:
1.  synchronized(obj),其中的obj对象有锁的功能,这是java语言在有创建synchronized()的时候就给了它这个用法。
2、3.我认为答案都是JVM在其中处理它们。
其实这块没必要那么深究它们,这些都是java语言的运行机制,是创建java语言的人就是这样定义,我们知道用就行了。
纯属个人理解,看看!
作者: 黄敏    时间: 2012-8-9 15:08
黑马王鹏 发表于 2012-8-9 15:03
这是java虚拟机的运行机制,也是java这门语言的规则:
1.  synchronized(obj),其中的obj对象有锁的功能, ...

我感觉不是,应该是一个类中有这个方法做这个判断吧,创建对线调用方法最判断吧
作者: pphdsny3    时间: 2012-8-9 15:13
黑马王鹏 发表于 2012-8-9 15:03
这是java虚拟机的运行机制,也是java这门语言的规则:
1.  synchronized(obj),其中的obj对象有锁的功能, ...

其实,第2、3个问题,JVM要实现它们也很简单,我想到的方法就是给他们一个全局的变量flag作为标识符不就可以了么,当有线程的进来了执行资源就改变flag为true,别的线程判断flag为true时就等呗,当线程执行完成了就改变flag为false,让别的线程去执行资源。
JVM也应该是用类似的方法去实现synchronized()上锁的功能。
这已经到了计算机底层的东西了,你还想深究的话,也可以自己去做实验呀!
作者: 黄敏    时间: 2012-8-9 15:17
黑马王鹏 发表于 2012-8-9 15:13
其实,第2、3个问题,JVM要实现它们也很简单,我想到的方法就是给他们一个全局的变量flag作为标识符不就 ...

呵呵,好主意,谢了
作者: 绽弧    时间: 2012-8-9 15:18
{:soso_e194:}求解,求真相,{:soso_e194:}
1,是谁给了这个对象 锁的功能?
2,这个对象是怎么判断一个线程进来了就改变这个对象标示位了?
3,一个线程走完同步代码块 ,又是怎么把标示位改变回去了呢?这其中是谁再操作这个对象了?
作者: 张雪磊    时间: 2012-8-9 15:52
本帖最后由 张雪磊 于 2012-8-9 16:28 编辑

我找到了Synchronized和Lock的底层实现方法,但是复制不过来,你们去看看吧http://wenku.baidu.com/view/41480552f01dc281e53af090.html

作者: 杜鹏云    时间: 2012-8-9 17:56
  所有对象都自动含有单一的锁。
  JVM负责跟踪对象被加锁的次数。如果一个对象被解锁,其计数变为0。在任务(线程)第一次给对象加锁的时候,计数变为1。每当这个相同的任务(线程)在此对象上获得锁时,计数会递增。
只有首先获得锁的任务(线程)才能继续获取该对象上的多个锁。
每当任务离开一个synchronized方法,计数递减,当计数为0的时候,锁被完全释放,此时别的任务就可以使用此资源。
当使用同步块时,如果方法下的同步块都同步到一个对象上的锁,则所有的任务(线程)只能互斥的进入这些同步块。
Lock 的锁是通过代码实现的,而 synchronized 是在 JVM 层面上实现的
synchronized 在锁定时如果方法块抛出异常,JVM 会自动将锁释放掉,不会因为出了异常没有释放锁造成线程死锁。但是 Lock 的话就享受不到 JVM 带来自动的功能,出现异常时必须在 finally 将锁释放掉,否则将会引起死锁。


在资源竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的。原因在于,编译程序通常会尽可能的进行优化synchronize,另外可读性非常好,不管用没用过5.0多线程包的程序员都能理解。

ReentrantLock:
ReentrantLock提供了多样化的同步,比如有时间限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在资源竞争不激烈的情形下,性能稍微比synchronized差点点。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock确还能维持常态。

Atomic:
和上面的类似,不激烈情况下,性能比synchronized略逊,而激烈的时候,也能维持常态。激烈的时候,Atomic的性能会优于ReentrantLock一倍左右。但是其有一个缺点,就是只能同步一个值,一段代码中只能出现一个Atomic的变量,多于一个同步无效。因为他不能在多个Atomic之间同步。






作者: 黄敏    时间: 2012-8-9 18:36
问题已解决




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2