多线程高并发系列(一)

基本概念

  • 进程:具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。
  • 线程:作为一个一个进程里面最小的执行单元他就叫一个线程,用简单的话说一个程序不同的执行路径叫做一个线程。

线程启动的几种方法

  1. new Thread().start()
  2. new Thread(Runnable).start()
  3. 线程池 ,如:Executors.newCacheThreadPool()

线程的方法

  • sleep,意思就是睡眠,当前线程暂停一段时间给别的线程去运行,sleep是如何复活的,有你的睡眠时间而定,等睡眠到规定的时间自动复活。
  • yield,就是当前线程正在执行的时候停止下来进入等待队列,回到等待队列在系统的调度算法里头还是依然有可能把你刚回去的这个线程拿回来继续执行,当然,更大可能是把原来的等待的那些线程拿出一个来执行,所以yield的意思就是我让出一下CPU,后面你能不能抢夺到我不管咯。
  • join,意思就是在自己当前线程加入你调用join的线程,本线程等待,等调用的线程运行完了,自己再去执行,t1和t2两个线程,在t1线程的某个点调用了t2.join,它会跑到t2去运行,t1等待t2运行完毕后继续t1运行(自己join自己没有意义)

线程状态

常见线程状态有六种:
当我们new一个线程时,还没有调用start()该线程处于新建状态
线程对象调用start()方法时候,它会被线程调度器来执行,也就是交给操作系统来执行了,那么操作系统来执行的时候,这个整个状态叫Runnable,Runnable内部有两个状态(1)Ready就绪状态(2)Running运行状态。就绪状态是说扔到CPU的等待队列里面排队等待CPU执行,等真正扔到CPU上去运行的时候叫做Running运行状态。(调用yile的时候会从Running状态跑到Ready状态中,线程调度器选中执行的时候又从Ready状态跑到Running状态去)
如果你线程顺利的执行完了就会进去(3)Teminated结束状态,(需要注意Teminated完了之后还可不可以回到new状态在调用start呢?这是不行的,完了这就是结束了)
在Runnable这个状态里头还有其他的一些状态的变迁
(4)TimeWaiting(5)Waiting(6)Blocked阻塞,在同步代码块的情况下没有得到锁就会阻塞状态,获得锁的时候是就绪状态运行。在运行的时候如调用了o.wait(),t.join(),LockSupport.park()进入Waiting状态,调用o.notify(),o.notifyAll(),LockSupport.unpark()
就又回到Running状态。TimeWaiting按照等待时间等待,等时间结束后自己就回去了。Thread.sleep(time),o.wait(time),t.join(time)
,LockSupport.parkNanos(),LockSupport.parkUntil()这些就是关于时间等待的方法。
问题:哪些是由JVM管理?哪些是由操作系统管理?
上面这些状态全是由JVM管理,因为JVM管理的时候也是需要通过操作系统,所以,那个是操作系统那个是JVM他俩分不开,JVM是跑到操作系统的一个普通程序。

synchronized

  • 静态方法static是没有this对象的,你不需要new一个对象就能执行这个方法,但如果这上面加一个synchronized的话就代表synchronized(T.class)。这里这个synchronized(T.class)锁的就是T类的对象。
  • synchronized一个属性:可重入,一个同步方法可以调用另一个同步方法,一个线程已经拥有某个对象的锁,再次申请的时候仍然会得到该对象的锁。
  • 异常锁,程序在执行过程中,如果出现异常,默认情况会释放锁。
  • synchronized(Object),避免锁String常量 Integer Long
  • synchronized 加上final修饰

synchronized底层实现

当我们使用synchronized的时候HotSport的实现是这样的:上来之后第一个去访问某把锁的线程 比如sync(Object),来了之后先在Object的头上面markword记录这个线程。(如果只有第一个线程访问的时候实际上是没有给Object加锁的,在内部实现的时候,只是记录这线程的ID(偏向锁)。
偏向锁如果有线程争用的话,就会升级为自旋锁(不进入CPU的就绪队列,用while循环尝试获取锁)
自旋转圈10次之后,升级会重量级锁,重量级锁就是去操作系统那里申请资源,这是一个锁升级的过程。
需要注意并不是CAS的效率就一定比系统锁要高,这个要区分实际情况。
执行时间短(加锁代码),线程数少,用自旋
执行时间长(加锁代码),线程数多,用系统锁。

volatile

  • 保证线程可见性
    • MESI
    • 缓存一致性协议
  • 禁止指令重排序
    • DCL单例(Double Chek Lock)
    • CPU原语 (读写屏障)

CAS

CompareAndSet,比较并且设定。
ABA问题:

  • 可加版本号解决
  • 如果是基础类型无所谓
  • 如果是引用类型,可能有问题(银行转账例子)

Atomic

为什么Atomic会比synchronized 快?
因为不加锁。synchronized 可能会去操作系统申请重量级锁,所以synchronized偏低,在这种情形下效率偏低。

ReentranLock

  • 必须必须必须手动释放锁(try...finally...)
  • 可以使用tryLock进行尝试锁定
  • lockInterruptibly 可被打断的加锁
  • 可指定公平锁/非公平锁

CountDownLatch(倒数

CyclicBarrier(循环栅栏)

Phaser(阶段)

ReadWriteLock

这个ReadWriteLock是读写锁。读写锁的概念其实就是共享锁和排他锁,读锁就是共享锁,写锁就是排他锁。

Semaphore(信号灯)

Exchanger(交换器)

LockSupport

  • LockSupport不需要synchronized加锁可以实现线程的阻塞和唤醒
  • LockSupport.unpark()可以先于LockSupport.park()执行,并且线程不会阻塞
  • 如果一个线程处于等待状态,连续调用两次park方法,就会使该线程永远不会被唤醒
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.println(i);
                if (i == 5) {
                    LockSupport.park();
                }
                //两次park就会让现场无法被唤醒
/*                if (i==8){
                    LockSupport.park();
                }*/
            }
        });
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t.start();
        LockSupport.unpark(t);
    }
}

LockSupport中park()和unpark()实现原理
park()和unpark()方法的实现是由Unsafe类提供的,而Unsafe类是由C和C++语言完成的,其实原理也比较好理解,他主要通过一个变量作为一个标识,变量值在0/1之间来回切换,当这个变量大于0的时候这个线程就获得了令牌

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,527评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,314评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,535评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,006评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,961评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,220评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,664评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,351评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,481评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,397评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,443评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,123评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,713评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,801评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,010评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,494评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,075评论 2 341

推荐阅读更多精彩内容