java代码锁 java上锁( 二 )


当需要put元素的时候 , 并不是对整个hashmap进行加锁,而是先通过hashcode来知道他要放在那一个分段中,然后对这个分段进行加锁,所以当多线程put的时候 , 只要不是放在一个分段中,就实现了真正的并行的插入 。
但是,在统计size的时候,可就是获取hashmap全局信息的时候,就需要获取所有的分段锁才能统计 。
分段锁的设计目的是细化锁的粒度,当操作不需要更新整个数组的时候,就仅仅针对数组中的一项进行加锁操作 。
七、偏向锁/轻量级锁/重量级锁
这三种锁是指锁的状态,并且是针对Synchronized 。在Java
5通过引入锁升级的机制来实现高效Synchronized 。这三种锁的状态是通过对象监视器在对象头中的字段来表明的 。
偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁 。降低获取锁的代价 。
轻量级锁是指当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能 。
重量级锁是指当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取到锁,就会进入阻塞,该锁膨胀为重量级锁 。重量级锁会让其他申请的线程进入阻塞,性能降低 。
八、自旋锁
在Java中 , 自旋锁是指尝试获取锁的线程不会立即阻塞 , 而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU 。
典型的自旋锁实现的例子,可以参考自旋锁的实现
java中的同步代码块,为什么随便放个对象,就可以锁住代码块呢?什么原理?synchronized(这里的对象java代码锁你看成一道门) {
这里是一个人进来java代码锁了,把门反锁了
需要同步操作的代码
这里是里面的人事情做完了,出去了 , 门开着其他人可以进了
}
至于怎么锁的,这是java和jvm的规定和实现细节,作为普通程序员没必要深入那么多 。
java中代码块被锁起来后多线程语句一直是一个线程在执行如下方代码,只有窗口1输出,求指点多线程临界资源肯定不能写线程内,要另外写一个类,另外while(Tickets=0)这里明显写成了死循环,所以以上代码思路完全错误
java代码右下角加锁能运行吗为什么能 。java代码右下角加锁能运行,是因为多线程共享的代码区域需要上锁,防止多线程同时访问代码块,造成线程安全问题 。
java加锁对象是一个锁标志 。按照先到先得的原则 , 如果有多个线程都会执行代码 , 并使用同一个对象作为锁,
synchronize(对象){
....
}
那么,先执行这段代码的那个线程,将会获得这个对象锁,而当这个线程执行这段代码的时候 , 其他线程也是使用这个对象作为锁的 , 就不能执行这段代码,知道最初得到这个锁的线程运行完这段代码,然后再把锁分配给下一个线程执行 。
如何使用java的锁机制可以在临界区代码开始的位置执行Lock类的lock方法,为代码块加锁,而在临界区的出口使用相同Lock实例的unlock方法,释放临界区资源 。
Demo2-12中,主线程先创建了一个lockTest对象test,然后将相同的test对象交给两个不同的线程执行 。子线程1获取到了lock后,开始执行before sleep输出语句,遇到sleep后,线程1阻塞将会放弃执行权,这时线程2可以获取执行权,当线程2执行lock方法时,发现锁已经被别的线程获?。?所以线程2阻塞等待lock的释放 。线程1从sleep中被唤醒后,将继续执行aftersleep语句,之后释放了锁 , 此时线程2从锁等待中被唤醒,执行临近区的内容,因此Demo2-12的输出是先线程1的两条语句 , 之后才输出线程2的两条语句 。而Demo2-13在没有锁的保护下,程序无法保证先将线程1的两条语句输出后再执行线程2的输出,因此,Demo2-13的输出结果是交叉的 。

推荐阅读