初识锁及synchronized

锁的种类

公平锁/非公平锁

    公平锁指多个线程按照申请锁的顺序来获取锁
    非公平锁是指多个线程不按照申请锁的顺序来获取锁,有可能造成线程饥饿现象
    ReentrantLock是通过AQS来实现线程调度,可以实现公平锁,但synchronized是非公平的,无法实现公平锁

可重入锁

    又叫递归锁,是指同一个线程,在外层方法获取到锁的时候,进入内层方法会自动获取锁

独享锁/共享锁

    独享锁是指该锁一次只能被一个线程所持有
    共享锁是指该锁可被多个线程所持有

互斥锁/读写锁

    独享锁/共享锁是一种广义的说法,互斥锁/读写锁是具体的实现
    互斥锁在Java中的实现就是ReentrantLock
    读写锁在Java中的实现就是ReadWriteLock

乐观锁/悲观锁

    悲观锁认为对于同一个数据的并发操作,一定会发生修改的,哪怕没有修改,也会认为修改。因此对于同一个数据的并发操作,悲观锁采取枷锁的形式。悲观的认为,不加锁的并发操作一定会出问题。
    乐观锁则认为对于同一数据的并发操作,是不会发生修改的,在更新数据的时候,会采用尝试更新。乐观的认为,不加锁的并发操作是没有事情的

分段锁

    分段锁是一种锁设计,并不是具体的一种锁,对于ConcurrentHashMap而言,其并发的实现就是通过分段锁的形式来实现高效的并发操作

偏向锁

    偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁,降低获取锁的代价

自旋锁(java.util.concurrent包下的几乎都是利用锁)

    自旋锁是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU

synchronized关键字

  • synchronized关键字 是一种同步锁
  • 原理是:一个线程访问对象中的Synchronized(this)同步代码块时,其他试图访问该对象的线程将会被阻塞。
package com.huixiang.synch;

import static java.lang.Thread.*;

public class SynchronizedTest {
    public static void main(String[] args) {
        System.out.println("使用关键字synchronized");
        SyncThread syncThread = new SyncThread();
        Thread syncThread1 = new Thread(syncThread, "SyncThread1");
        Thread syncThread2 = new Thread(syncThread, "SyncThread2");
        syncThread2.start();
        syncThread1.start();
    }

}
class SyncThread implements Runnable{

    private static int count;
    public SyncThread(){
        count = 0;
    }
    //实现run方法
    @Override
    public void run() {
        synchronized (this){
            for (int i =0;i<5;i++){
                try {
                    //currentThread().getName()获取当前线程的名字
                    System.out.println("线程name"+currentThread().getName());
                    //休眠100ms
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static int getCount() {
        return count;
    }
}

在这里插入图片描述

分析
  • 当两个并发线程访问同一个对象中的synchronized代码块时,在同一时刻只能有一个线程得到执行,另一个线程受阻塞,必须等待当前线程执行完这个代码块之后才能执行该代码块。
  • 两个线程是互斥的,因为在执行synchronized代码块是会锁定当前的对象,只有执行完该代码块才能释放该对象锁,下一个线程才能执行并锁定该对象。
修饰一个方法

synchronized修饰一个方法很简单就是在方法的前面加synchronized。

将上边代码块改为
	@Override
	public synchronized void run() {
        for (int i =0;i<5;i++){
            try {
                //currentThread().getName()获取当前线程的名字
                System.out.println("线程name"+currentThread().getName());
                //休眠100ms
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
分析
  • 虽然可以使用synchronized来定义方法,但是synchronized并不属于方法定义的一部分,因此,synchronized并不能被继承。如果在父类的某个方法中使用了synchronized关键字,而子类中覆盖了这个方法,在子类中的这个方法默认情况下并不是同步的,而必须显式的在子类的这个方法中加上synchronized关键字才可以。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值