这时候,殷落花开口说道:“小民,赵前辈说的对,洪绝即便有错,那也应该由世俗界的法律去约束他。看在我的面子上,就把他交给警察去管吧。”

“千年智慧轮拥有追踪千年神器的力量,所以他要找到你是很容易的。”

网上有什么兼职可以赚钱方法

“是有的,能打败你这样的高手是一件值得开心的事情。”暗游戏承认道。
“靠,我很赶时间啊!”雪飞鸿暗中偷笑,可是他还不肯轻易就答应,非引得这小寡妇苦苦哀求。

“我最远只去过河西,去过居延海,万马奔腾,沿着居延海疾奔,那种壮观的景色我至今难以忘怀。”

知识点干货—多线程同步【6】之synchronized


“明日复明日,明日何其多。
我生待明日,万事成蹉跎。
世人若被明日累,春去秋来老将至。
朝看水东流,暮看日西坠。
百年明日能几何?请君听我明日歌。
明日复明日,明日何其多!
日日待明日,万世成蹉跎。
世人皆被明日累,明日无穷老将至。
晨昏滚滚水东流,今古悠悠日西坠。
百年明日能几何?请君听我明日歌。”

这首《明日歌》是明朝的钱福所写。大意是,
明天又一个明天,明天何等的多。
我的一生都在等待明日,什么事情都没有进展。
世人和我一样辛苦地被明天所累,一年年过去马上就会老。
早晨看河水向东流逝,傍晚看太阳向西坠落才是真生活。
百年来的明日能有多少呢?请诸位听听我的《明日歌》。

这首诗七次提到“明日”,诗人在作品中告诫和劝勉人们要牢牢地抓住稍纵即逝的今天,要珍惜时间,今日的事情今日做,不要拖到明天,不要蹉跎岁月。不要把任何计划和希望寄托在未知的明天。诗歌的意思浅显,语言明白如话,说理通俗易懂。给人的启示是:世界上的许多东西都能尽力争取和失而复得,只有时间难以挽留。人的生命只有一次,时间永不回头。不要今天的事拖明天,明天拖后天,要“今天的事,今日毕”。告诫我们不要学寒号鸟,要珍惜时间,不要把事情都放到明天,今天的事情今天搞定。

继续总结多线程同步常用的方法或者类,之前介绍了CountDownLatch,CyclicBarriar和Exchanger,Phaser 以及Semaphore,这次介绍一个大家比较熟悉的关键字--synchronized。大多数人应该或多或少的使用过它,那我们对它是所有用法都彻底了解吗?这个就不见的了,今天我们就全方位的介绍一下它。

1、定义

先看一下百度百科给出的定义:“synchronized--Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。然而,当一个线程访问object的一个加锁代码块时,另一个线程仍可以访问该object中的非加锁代码块。”
什么意思呢?就是说synchronized是Java中用来对对象和方法或者代码块进行加锁的一种方法,借助它可以在多线程并发时,保证同一时刻只有一个线程执行某个同步方法或代价块,这样能充分保证线程按顺序执行,保证它们同步进行,按照我们的逻辑使多线程按我们的心意来依次执行,这也是一种解决多线程同步的方法。

2、对象锁和类锁的概念

在使用synchronized前,我们要先理解两个概念,对象锁和类锁。

对象锁
对象锁是指Java为临界区(指程序中的一个代码段)synchronized(Object)语句指定的对象进行加锁。它用于程序片段或者method上,此时将获得对象的锁,所有想要进入该对象的synchronized的方法或者代码段的线程都必须获取对象的锁,如果没有,则必须等其他线程释放该锁。
当一个对象中有synchronized method或synchronized block的时候调用此对象的同步方法或进入其同步区域时,就必须先获得对象锁。如果此对象的对象锁已被其他调用者占用,则需要等待此锁被释放。

类锁
实际上是没有这个概念的,但是为了区分对象锁的不同使用场景,我们增加了一个类锁这样的概念。对象锁指的是对象的某个方法或代码块进行加锁,那类锁指的是针对类方法或者类变量进行加锁。由于一个class不论被实例化多少次,其中的静态方法和静态变量在内存中都只有一份。所以,一旦一个静态方法被申明为synchronized,此类所有的实例化对象在调用此方法,共用同一把锁,所以我们称之为类锁。
在程序中可以尝试用以下方式获取类锁

synchronized (xxx.class) {...}
synchronized (Class.forName("xxx")) {...}

同时获取类锁和对象锁是可以的,并不会产生问题。但使用类锁时要格外注意,因为一旦产生类锁的嵌套获取的话,就会产生死锁,因为每个class在内存中都只能生成一个Class实例对象。

3、使用方法

了解了对象锁和类锁后,我们知道了synchronized可以用于多个场景,既可以修改代码块和方法,还可以用来修饰类方法和类。虽然锁针的对象不同,但它们的含义是一样的。

synchronized具体有如下四种使用场景:
(1)、修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象。多个线程在同时使用这个对象的此代码块时会遇到对象锁,需要进行同步等待;

代码示例:


class DemoThread implements Runnable {

    private static int count;

    public DemoThread() {
        count = 0;
    }

    public  void run() {
        synchronized(this) {
            for (int i = 0; i < 5; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + ":" + (count++));
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public int getCount() {
        return count;
    }
}

DemoThread demoThread = new DemoThread();
Thread thread1 = new Thread(demoThread, "DemoThread1");
Thread thread2 = new Thread(demoThread, "DemoThread2");

thread1.start();
thread2.start();

结果如下:

DemoThread1:0 
DemoThread1:1 
DemoThread1:2 
DemoThread1:3 
DemoThread1:4 
DemoThread2:5 
DemoThread2:6 
DemoThread2:7 
DemoThread2:8 
DemoThread2:9

分析:当两个并发线程(thread1和thread2)同事访问同一个对象(demoThread)中的synchronized代码块时,在同一时刻只能有一个线程执行,另一个线程阻塞在synchronized位置,必须等待正在访问的线程执行完这个代码块以后才能执行该代码块。所以才会看到这样的结果,开始只有DemoThread1的Log,DemoThread1执行完成后才能看到DemoThread的Log。

这里需要注意一下,当一个线程访问对象的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该对象中的非synchronized(this)同步代码块。也就是说如果thread1正在访问synchronized修饰的代码块,thread2虽然此时无法访问这个代码块,但它可以访问其他的代码块。

(2)、修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象。在多线程执行时和同步代码块相同,针对的是某个对象;

代码示例:

class DemoThread implements Runnable {
    private static int count;

    public DemoThread() {
        count = 0;
    }

    public synchronized void run() {
        for (int i = 0; i < 5; i++) {
            try {
                System.out.println(Thread.currentThread().getName() + ":" + (count++));
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public int getCount() {
        return count;
    }
}

DemoThread demoThread = new DemoThread();
Thread thread1 = new Thread(demoThread, "DemoThread1");
Thread thread2 = new Thread(demoThread, "DemoThread2");

thread1.start();
thread2.start();

结果如下:

DemoThread1:0 
DemoThread1:1 
DemoThread1:2 
DemoThread1:3 
DemoThread1:4 
DemoThread2:5 
DemoThread2:6 
DemoThread2:7 
DemoThread2:8 
DemoThread2:9

可以看到他们的执行结果是相同的。既然结果相同,那修饰代码块和修改方法名有什么区别呢?
这个问题也是synchronized的缺陷。
synchronized的缺陷:当某个线程进入同步方法获得对象锁,那么其他线程访问这里对象的同步方法时,必须等待或者阻塞,这对高并发的系统是致命的,这很容易导致系统的崩溃。如果某个线程在同步方法里面发生了死循环,那么它就永远不会释放这个对象锁,那么其他线程就要永远的等待,这问题一旦出现就是是一个致命的问题。既然无法完全避免这种缺陷,那么就应该将风险降到最低。同步代码块就是为了降低风险而存在的。因为如果某一线程调用synchronized修饰的代码方法,那么当某个线程进入了这个方法之后,这个对象其他同步方法都不能被其他线程访问了。假如这个方法需要执行的时间很长,那么其他线程会一直阻塞,影响到系统的性能。而如果这时用synchronized来修饰代码块,情况就不同了,这个方法加锁的对象是某个对象,跟执行这行代码的对象或者承载这个方法的对象没有关系,那么当一个线程执行这个方法时,其他同步方法仍旧可以访问,因为他们持有的锁不一样。

(3)、修饰一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象。多线程在使用此方法时,会涉及到类锁。

代码示例:

class DemoThread implements Runnable {
    private static int count;

    public DemoThread() {
        count = 0;
    }

    public synchronized static void method() {
        for (int i = 0; i < 5; i ++) {
            try {
                System.out.println(Thread.currentThread().getName() + ":" + (count++));
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public synchronized void run() {
        method();
    }
}
DemoThread demoThread = new DemoThread();
Thread thread1 = new Thread(demoThread, "DemoThread1");
Thread thread2 = new Thread(demoThread, "DemoThread2");

thread1.start();
thread2.start();

结果如下:

DemoThread1:0 
DemoThread1:1 
DemoThread1:2 
DemoThread1:3 
DemoThread1:4 
DemoThread2:5 
DemoThread2:6 
DemoThread2:7 
DemoThread2:8 
DemoThread2:9

可以看到结果和上两例相同。DemoThread1和DemoThread2是DemoThread的两个对象,但在thread1和thread2并发执行时却保持了线程同步。这是因为run中调用了静态方法method,而静态方法是属于类的,所以syncThread1和syncThread2相当于用了同一把锁。

(4)、修饰一个类,其作用的范围是synchronized后面括号括起来的部分,作用的对象是这个类的所有对象。多线程使用此类时涉及到类锁。

代码示例:

class DemoThread implements Runnable {
    private static int count;

    public DemoThread() {
        count = 0;
    }

    public static void method() {
        synchronized(DemoThread.class) {
            for (int i = 0; i < 5; i ++) {
                try {
                    System.out.println(Thread.currentThread().getName() + ":" + (count++));
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public synchronized void run() {
        method();
    }
}
DemoThread demoThread = new DemoThread();
Thread thread1 = new Thread(demoThread, "DemoThread1");
Thread thread2 = new Thread(demoThread, "DemoThread2");

thread1.start();
thread2.start();

结果如下:

DemoThread1:0 
DemoThread1:1 
DemoThread1:2 
DemoThread1:3 
DemoThread1:4 
DemoThread2:5 
DemoThread2:6 
DemoThread2:7 
DemoThread2:8 
DemoThread2:9

可以看到结果也是相同的。synchronized作用于一个类时,是给这个类加锁,类的所有对象用的是同一把锁。

4、总结

synchronized对于使用过的人来说应该比较好理解,也更容易学习它的高级用法,运用起来会显得很轻松;对于没有使用过的,可能只是停留在理解概念的层面,实际在使用时还是不太好下手,不知在何时何地来使用。所以解决不熟悉的唯一办法就是要勇敢大胆的去使用它,不要怕出错,多实践和多练习,这样才能很好的掌握它。


本公众号将以推送Android各种技术干货或碎片化知识,以及整理老司机日常工作中踩过的坑涉及到的经验知识为主,也会不定期将正在学习使用的新技术总结出来进行分享。每天一点干货小知识把你的碎片时间充分利用起来。

当前文章:http://hnhdqp.com/R/77745.html

发布时间:2018-11-18 04:27:31

投票赚钱平台那个好 暑假在家里可以干什么 想在家做手工去哪拿货 在家就能工作 投资理财入门看什么书 薅羊毛苏宁 官方网上兼职是真的吗 杭州星巴克怎么兼职

编辑:安龙

相关新闻

退学费骗局大量来袭 360手机卫士可精准拦截

2018-11-18 03:12:17

三沙统克娜广告传媒有限公司

用欠薪应急周转金倒逼责任

2018-11-18 02:02:21

景德镇究悍商贸有限公司

7成人站在心理悬崖

2018-11-18 00:39:47

包头咐衣有限责任公司

最佳Android Wear 智能手表推荐

2018-11-18 04:21:39

西双版纳位孤网络技术有限公司

热门推荐

  • 地球70年前进入“人类世”:在哪里标记引全球争议
  • 从CMOS传感器角度看,2018年我们能买到什么新相机
  • 《POP TEAM EPIC》活动人数过多 判定危险强迫终止
  • 谷歌出品:Datally应用可帮你节省手机流量
  • Switch在日本依旧一机难求,XboxOne X首发也被抢光
  • 33分15秒!2017天猫双11进口首单完成配送签收
  • 从来不玩竞技游戏的用户也开始吃鸡了 它能压垮国产游戏?
  • 苹果iPhone X野生上手视频:应用竟然闪退……
  • 微信公众号支付|微信H5支付|微信扫码支付|小程序支付|APP微信支付解决方案总结
  • 美司令呐喊要在东海南海维护宁静:我们能打头阵
  • 河北新闻网版权所有 本站点信息未经允许不得复制或镜像 法律顾问:适合在家干的兼职 手游能赚钱吗
  • 网上如何做兼职 copyright ? 2000 - 2016
  • 新闻热线:0311-67563366 广告热线:0311-67562966 新闻投诉:0311-67562994
  • 冀ICP备 09047539号-1 | 互联网新闻信息服务许可证编号:1312006002
  • 广播电视节目制作经营许可证(冀)字第101号|信息网络传播视听节目许可证0311618号
  • 千元创业赚钱好项目 人肉代购怎么赚钱 想找个兼职,赚钱的买卖 新人网赚做什么