同步的方案是将一段代码声明为原子操作,只有执行完毕才可以由其他线程执行,执行过程中不可中断,即使出现不可屏蔽的中断,也必须进行回退。
加锁一般分为互斥锁,可重入锁和读写锁。可重入锁可以用来解决当代码块是递归调用时,普通的互斥锁会产生死锁的问题。因为某个线程已经获得锁,当它递归调用自己的时候,会再次申请加锁,此时就会死锁,而可重入锁可以在线程已经获取到锁的情况下,递归调用自己时,直接再次使用自己已经获得的锁。
读写锁的特点是,多个读者线程可以同时读,但是写者线程是互斥的,也就是同一时间最多只能有一个写者,而且也与读者线程优先,也就是当有写者时,优先调度写者线程运行,并将后续的读者线程调度为阻塞态。
同步和加锁的对比
从性能上来说,在资源的竞争不激烈的情况下,两中方式的性能接近,而在有大量线程同时激烈地竞争资源时,此时Lock的性能要远远优于synchronized。同步的互斥锁可重入但不可中断,排斥所有其他线程,即使二者都是读者也不行,此时读写锁更好。但同步的互斥锁在synchronized块结束时,会自动释放锁,在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;lock一般需要在finally中自己释放,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要手动在finally块中释放锁。我们在具体使用时,要根据实际情况做最合适的选择。