精华内容
下载资源
问答
  • 线程之初体验

    2015-06-25 15:45:58
    之前看《编程思想》的多线程章节,看的云里雾里,知道线程几个方法,却依旧知道线程到底是什么?书上都写线程是进程的模块,共享线程的资源,可是这跟多线程编程有毛线的关系,呜呜。。。 线程其实也是...
    一直觉得多线程是学Java的一个分水岭,懂多线程才算入门。
    之前看《编程思想》的多线程章节,看的云里雾里,知道线程类有哪几个方法,却依旧不知道线程到底是什么?书上都写线程是进程的模块,共享线程的资源,可是这跟多线程编程有毛线的关系,呜呜。。。

    线程其实也是用户自定义的任务,不要过多的强调线程的属性,而忽略了线程最基本的属性。
    你可以在线程类的run()方法中定义自己的任务,就跟正常的Java代码一样,也正是因为这样,所以创建线程时才需要覆写run()方法,要不来虚拟机是不知道你给它的任务不是么?
    所不同的是,JVM提供了对这个类的一些调度方法和管制,所以会有Thread.start()开始执行run方法、Thread.yield()释放处理器同其他线程共同竞争处理器资源等方法;
    多线程编程,在于如何安全高效地组织你的任务,让它们能协同地完成任务。
    展开全文
  • 多线程的同步主要是对多个线程共享一资源时的访问控制,避免出现“乱套”现象。Java提供多种机制进行同步控制,比如锁和条件对象,synchronized关键字等。而集合经常作为这种资源被多个线程共享,而且集合框架中...
  • 锁是用来控制多线程访问共享资源的方式,一般的讲,个锁能够防止多个线程同时访问共享资源。对于 Java 中的锁而言,根据分类标准我们把锁分为以下 7 大类别,分别是:偏向锁/轻量级锁/重量级锁;可重入锁/非可重入...

    Java中哪几种锁?分别有什么特点?

    本文中我们一起学习Java中锁的分类及其特点。

    锁是用来控制多线程访问共享资源的方式,一般的讲,一个锁能够防止多个线程同时访问共享资源。

    对于 Java 中的锁而言,根据分类标准我们把锁分为以下 7 大类别,分别是:

    1. 偏向锁/轻量级锁/重量级锁;

    2. 可重入锁/非可重入锁;

    3. 共享锁/独占锁;

    4. 公平锁/非公平锁;

    5. 悲观锁/乐观锁;

    6. 自旋锁/非自旋锁;

    7. 可中断锁/不可中断锁。

    1. 偏向锁/轻量级锁/重量级锁

    第一种分类是偏向锁/轻量级锁/重量级锁,这三种锁特指 synchronized 锁的状态,通过在对象头中的 mark word 来表明锁的状态。

    • 偏向锁

    如果自始至终,对于这把锁都不存在竞争,那么其实就没必要上锁,只需要打个标记就行了,这就是偏向锁的思想。一个对象被初始化后,还没有任何线程来获取它的锁时,那么它就是可偏向的,当有第一个线程来访问它并尝试获取锁的时候,它就将这个线程记录下来,以后如果尝试获取锁的线程正是偏向锁的拥有者,就可以直接获得锁,开销很小,性能最好。

    • 轻量级锁

    JVM 开发者发现在很多情况下,synchronized 中的代码是被多个线程交替执行的,而不是同时执行的,也就是说并不存在实际的竞争,或者是只有短时间的锁竞争,用 CAS 就可以解决,这种情况下,用完全互斥的重量级锁是没必要的。轻量级锁是指当锁原来是偏向锁的时候,被另一个线程访问,说明存在竞争,那么偏向锁就会升级为轻量级锁,线程会通过自旋的形式尝试获取锁,而不会陷入阻塞。

    • 重量级锁

    重量级锁是互斥锁,它是利用操作系统的同步机制实现的,所以开销相对比较大。当多个线程直接有实际竞争,且锁竞争时间长的时候,轻量级锁不能满足需求,锁就会膨胀为重量级锁。重量级锁会让其他申请却拿不到锁的线程进入阻塞状态。

    dcd311b6c89dc99c297989fd093455a1.png

    你可以发现锁升级的路径:无锁→偏向锁→轻量级锁→重量级锁。

    综上所述,偏向锁性能最好,可以避免执行 CAS 操作。而轻量级锁利用自旋和 CAS 避免了重量级锁带来的线程阻塞和唤醒,性能中等。重量级锁则会把获取不到锁的线程阻塞,性能最差。

    2. 可重入锁/非可重入锁

    第 2 个分类是可重入锁和非可重入锁。可重入锁指的是线程当前已经持有这把锁了,能在不释放这把锁的情况下,再次获取这把锁。同理,不可重入锁指的是虽然线程当前持有了这把锁,但是如果想再次获取这把锁,也必须要先释放锁后才能再次尝试获取。

    对于可重入锁而言,最典型的就是 ReentrantLock 了,正如它的名字一样,reentrant 的意思就是可重入,它也是 Lock 接口最主要的一个实现类。

    3.共享锁/独占锁

    第 3 种分类标准是共享锁和独占锁。共享锁指的是我们同一把锁可以被多个线程同时获得,而独占锁指的就是,这把锁只能同时被一个线程获得。我们的读写锁,就最好地诠释了共享锁和独占锁的理念。读写锁中的读锁,是共享锁,而写锁是独占锁。读锁可以被同时读,可以同时被多个线程持有,而写锁最多只能同时被一个线程持有。

    4.公平锁/非公平锁

    第 4 种分类是公平锁和非公平锁。公平锁的公平的含义在于如果线程现在拿不到这把锁,那么线程就都会进入等待,开始排队,在等待队列里等待时间长的线程会优先拿到这把锁,有先来先得的意思。而非公平锁就不那么“完美”了,它会在一定情况下,忽略掉已经在排队的线程,发生插队现象。

    5.悲观锁/乐观锁

    第 5 种分类是悲观锁,以及与它对应的乐观锁。悲观锁的概念是在获取资源之前,必须先拿到锁,以便达到“独占”的状态,当前线程在操作资源的时候,其他线程由于不能拿到锁,所以其他线程不能来影响我。而乐观锁恰恰相反,它并不要求在获取资源前拿到锁,也不会锁住资源;相反,乐观锁利用 CAS 理念,在不独占资源的情况下,完成了对资源的修改。

    6.自旋锁/非自旋锁

    第 6 种分类是自旋锁与非自旋锁。自旋锁的理念是如果线程现在拿不到锁,并不直接陷入阻塞或者释放 CPU 资源,而是开始利用循环,不停地尝试获取锁,这个循环过程被形象地比喻为“自旋”,就像是线程在“自我旋转”。相反,非自旋锁的理念就是没有自旋的过程,如果拿不到锁就直接放弃,或者进行其他的处理逻辑,例如去排队、陷入阻塞等。

    7.可中断锁/不可中断锁

    第 7 种分类是可中断锁和不可中断锁。在 Java 中,synchronized 关键字修饰的锁代表的是不可中断锁,一旦线程申请了锁,就没有回头路了,只能等到拿到锁以后才能进行其他的逻辑处理。而我们的 ReentrantLock 是一种典型的可中断锁,例如使用 lockInterruptibly 方法在获取锁的过程中,突然不想获取了,那么也可以在中断之后去做其他的事情,不需要一直傻等到获取到锁才离开。

    总结

    本文中我们首先会对锁的分类有一个整体的概念,了解锁究竟有哪些分类标准。然后在后续的课程中,会对其中重要的锁进行详细讲解。

    展开全文
  • 1.为什么有多线程同步?...2.JVM对哪类线程共享的数据进行加锁机制?  1)保存在堆中的实例变量---对象锁,就是有个和对象相关联的监视器  2)保存在方法区的变量---锁实际上用对象锁来实现,当JVM装载


    以下总结摘自(加上一点自己的理解):http://blog.csdn.net/yangzhijun_cau/article/details/6432216

    1.为什么有多线程同步?Java中多线程同步的机制是什么?

        当多个线程同时竞争同一资源时候,为了防止出现数据不一致性问题,需要有同步机制。而同步机制是通过锁的概念来实现的。


    2.JVM对哪类线程共享的数据进行加锁机制?

       1)保存在堆中的实例变量---对象锁,就是有一个和对象相关联的监视器

        2)保存在方法区的类变量---类锁实际上用对象锁来实现,当JVM装载一个class文件时候,他会创建一个java.lang.class类的实例。所以类锁锁住的是那个类的Class对象。相应的也会有一个类对象监视器


    3.何时上锁?

        这里对象锁是Java虚拟机内部使用,在Java程序中只要使用synchronized块或者synchronized方法就可以标志一个监视区域,当每次进入一个监视区域时,JVM都会自动锁上对象或者类。


    4.多线程同步时,所持有的对象锁有什么要求?

       共享且唯一的


    5.实例验证线程同步时,锁持有的是都为同一对象锁?只有是唯一共享的对象锁,多线程才能实现同步哦

    //10个线程在控制台上数数,从1数到9999。理想情况下,我们希望看到一个线程数完,然后才是另一个线程开始数数。

    实例1如下

    public class ThreadTest extends Thread {   
        private int threadNo;   
        public ThreadTest(int threadNo) {   
            this.threadNo = threadNo;   
        }   
        public static void main(String[] args) throws Exception {   
            for (int i = 1; i < 10; i++) {   
               new ThreadTest(i).start();   
                Thread.sleep(1);   
            }   
         }   
        
        @Override  
         public synchronized void run() {   
            for (int i = 1; i < 10000; i++) {   
                System.out.println("No." + threadNo + ":" + i);   
            }   
         }   
     }   

    结果程序并没有按照顺序报数。但是程序中已经使用了synchronized关键字了呀,这是怎么回事?首先这是一个ThreadTest实例对象锁,而在main方法中,共产生了十个实例对象,每个线程都持有自己对象的那个对象锁,因此不能实现同步效果。

    实例2

    public class ThreadTest2 extends Thread {   
     private int threadNo; private String lock;   
     public ThreadTest2(int threadNo, String lock) {   
      this.threadNo = threadNo;   
         this.lock = lock;   }   
    public static void main(String[] args) throws Exception {   
       String lock = new String("lock");   
         for (int i = 1; i < 10; i++) {     
      new ThreadTest2(i, lock).start();   
          Thread.sleep(1);   
         }   
      }     
    public void run() {     
     synchronized (lock) {   
          for (int i = 1; i < 10000; i++) {   
           System.out.println("No." + threadNo + ":" + i);   
        }      
     }     
     }   
     }  

           该程序通过在main方法启动10个线程之前,创建了一个String类型的对象(对象保存在堆中)。并通过ThreadTest2的构造函数,将这个对象赋值 给每一个ThreadTest2线程对象中的私有变量lock。根据Java方法的传值特点,我们知道,这些线程的lock变量实际上指向的是堆内存中的 同一个区域,即存放main函数中的lock变量的区域。
            程序将原来run方法前的synchronized关键字去掉,换用了run方法中的一个synchronized块来实现。这个同步块的对象锁,就是 main方法中创建的那个String对象。换句话说,他们指向的是同一个String类型的对象,对象锁是共享且唯一的!因此会看到顺序报数的结果。

    实例3

     public class ThreadTest3 extends Thread {   
    
     2    
     3     private int threadNo;   
     4     private String lock;   
     5    
     6     public ThreadTest3(int threadNo) {   
     7         this.threadNo = threadNo;   
     8     }   
     9    
    10     public static void main(String[] args) throws Exception {   
    11        
    12         for (int i = 1; i < 20; i++) {   
    13             new ThreadTest3(i).start();   
    14             Thread.sleep(1);   
    15         }   
    16     }   
    17    
    18     public static synchronized void abc(int threadNo) {   
    19         for (int i = 1; i < 10000; i++) {   
    20               
    21                 System.out.println("No." + threadNo + ":" + i);           
    22         }   
    23     }   
    24    
    25     public void run() {   
    36         abc(threadNo);   
    27     }   
    28 }  
    同样,程序能按照顺序报数。这段代码没有使用main方法中创建的String对象作为这10个线程的线程锁。而是通过在run方法中调用本线程中一个静态的同步方法abc而实现了线程的同步。这里synchroniaed静态方法是用类实例(唯一)来做对象锁的。


    于是,对于synchronized我们知道:

    1、对于同步的方法或者代码块来说,必须获得对象锁才能够进入同步方法或者代码块进行操作;
    2、如果采用method级别的同步,则对象锁即为method所在的对象,如果是静态方法,对象锁即指method所在的Class对象(唯一);
    3、对于代码块,对象锁即指synchronized(abc)中的abc;
    4、对于第一种情况,对象锁即为每一个线程对象,因此有多个,所以同步失效,第二种共用同一个对象锁lock,因此同步生效,第三个因为是static,因此对象锁为ThreadTest3的class 对象,因此同步生效。

    如上述正确,则同步有两种方式,同步块和同步方法

    如果是同步代码块,则对象锁需要编程人员自己指定,一般有些代码为synchronized(this)只有在单态模式才生效;(本类的实例有且只有一个)

    如果是同步方法,则分静态和非静态两种 

    静态方法则一定会同步,非静态方法需在单例模式才生效,推荐用静态方法(不用担心是否单例)。

    在Java多线程编程中,最常见的synchronized关键字实际上是依靠对象锁的机制来实现线程同步的。



    展开全文
  • ===第九章 多线程 ...无论使用种方式,最终都必须依靠Thread才能启动多线程; 继承Thread类不能实现资源共享; 实现Runnable接口可以实现资源共享; Java程序每次运行至少启动两个线程,main线程和垃

    ===第九章 多线程


    一个类只要继承了Thread类,就称为多线程实现类;
    Thread子类中覆写的run() 方法为线程的主体;
    继承Thread类的类只能调用一次start() 方法;
    无论使用哪种方式,最终都必须依靠Thread类才能启动多线程;
    继承Thread类不能实现资源共享;
    实现Runnable接口可以实现资源共享;
    Java程序每次运行至少启动两个线程,main线程和垃圾收集线程;
    主线程有可能最先执行完,此时其他线程不受影响;
    要强制某一线程运行,可用join()方法;
    优先级越高,越有可能先被执行,但最终执行顺序由CPU调度决定;
    线程的默认优先级(主方法)是NORM_PRIORITY(5);
    多个线程共享同一资源时需要使用synchronized进行同步;
    过多的同步就有可能产生死锁;
    展开全文
  • Semaphore信号量的总结

    2017-12-15 09:35:36
    但是另外,当一个资源个副本可用的时候像公共设施一样,这种就方式就适用了,因为这个资源可以同时被一定数量的线程使用,而仅仅是拿到锁的哪一线程。 Seamaphore(se mer for)是一个计数信号量,...
  • (1)如果设计正确,多线程程序可以通过提高处理器资源的利用率来提升系统吞吐率 (2)建模简单:通过使用线程可以讲复杂并且异步的工作流进一步分解成组简单并且同步的工作流,每个工作流在个单独的线程...
  • java基础知识问答

    2017-03-09 11:30:42
    地址空间和其它资源:进程间相互独立,同一进程的各线程共享。某进程内的线程在其它进程可见 b.通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助...
  • 内核中的同步和并发 其实并发和同步是操作系统设计中的个核心问题,随着CPU的发展,多核多线程已经成为了...不管是哪类并发,都存在共享资源(临界区)保护的问题。临界区保护通常采用的手段就是串行化,其中最常见
  • //,用来管理URL,由各抓取线程共享 private URLMap urlmap; //已成功处理URL总数 private int count; //目标完成任务总数 private int total; //管理所有的抓取线程,必要时进行关闭,由于抓取线程...
  • 与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。...
  • java 面试题 总结

    2009-09-16 08:45:34
    与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。...
  • JAVA面试题最全集

    2010-03-13 13:09:10
    35.java除了8种基本类型外,在虚拟机里还有哪一种,有什么作用? 36.除了使用new关键字创建对象意外,试列举另外三种以上创建实例的方式? 37.classloader中,JDK的API、Classpath中的同web-inf中的class加载方式有...
  • java面试宝典

    2013-02-28 16:04:01
    70、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? 17 71、启动个线程是用run()还是start()? 17 72、当个线程进入个对象的个synchronized方法后,其它线程是否可进入此对象的其它方法? 18 73...
  • 千方百计笔试题大全

    2011-11-30 21:58:33
    70、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? 17 71、启动个线程是用run()还是start()? 17 72、当个线程进入个对象的个synchronized方法后,其它线程是否可进入此对象的其它方法? 18 73...
  • ThreadLocal通常用来共享数据,当你想在个方法中使用某个变量,这个变量是当前线程的状态,其它线程不依赖这个变量,你第时间想到的就是把变量定义在方法内部,然后再方法之间传递参数来使用,这个方法能解决...
  • C#微软培训教材(高清PDF)

    千次下载 热门讨论 2009-07-30 08:51:17
    本书着重介绍语言本身,比较少涉及应用,不错的入门书,从头讲起,不怕明白。 <<page 1>> page begin==================== 目 目目 目 录 录录 录 第部分 C#语言概述.4 第章 第章第章 第...
  • C#微软培训资料

    2014-01-22 14:10:17
    14.2 态 性 .159 14.3 抽象与密封 .163 14.4 继承中关于属性的一些问题.169 14.5 小 结 .172 第四部分 深入了解 C#.174 第十五章 接 口 .174 15.1 组件编程技术 .174 15.2 接 口 定 义 .177 15.3 ...
  • C++网络爬虫项目

    2018-07-04 00:59:17
    管理器、统一资源定位符队列、域名解析线程等在内的个底层设施,提供诸 如初始化、执行路输入输出循环、启动抓取任务等外部接口。 2.3.5. 主线程(main) 主函数,处理命令行参数,初始化应用程序对象,进入路I/...
  • A) 类是描述了同一类对象具有的数据和行为。Java语言中的类将这些数据和行为进行封装,形成了一种复合数据类型 B) 在Java的类中可以有三类内容分别是数据的定义、基本输出语句、函数的定义。 C) Java中的封装就是将...
  • oracle数据库经典题目

    2011-02-17 15:05:20
    2.如果一个服务器进程非正常终止,Oracle系统将使用下列哪一个进程来释放它所占用的资源?( D ) A.DBWR B.LGWR C. SMON D.PMON 3. 如果要查询数据库中所有表的信息,应当使用下列哪种数据字典视图?( A ) A. ...
  • 毫不含糊先开启个子线程来采集数据并将数据存入到内存,再开启个定期任务的子线程负责从内存中取数据,并将数据存入数据库,有一点需要注意下,内存的数据结构我们用ArrayList实为不妥,多线程中有数据同步的...
  • 至于说看哪一本,你可以找对应的电子书,挑一个章节试读一下,符合你的胃口就选择这一本继续读下去。 如果你已经有几年的编码经验,又想把代码写好,建议你挑基本读读,吸收每本书的精华。 计算机网络 学什么? ...
  • 新版Android开发教程.rar

    千次下载 热门讨论 2010-12-14 15:49:11
    也有分析认为,谷歌并想做个简单的手机终端制造商或者软件平台开发商,而意在一统传统互联网和 移 动互联网。----------------------------------- Android 编程基础 4 Android Android Android Android 手机新...
  • ● 增强的安全性:每个程序集还可以包含内置的安全信息,这些信息可以准确地指出种类型的用户或进程可以调用什么的哪些方法。这样就可以非常准确地控制用户部署的程序集的使用方式。 ● 对安装没有任何影响:有...
  • 说明 : 指定在共享服务器环境中可同时运行的共享服务器进程的最大数量。 值范围: 根据操作系统而定。 默认值 : 20 dispatchers: 说明 : 为设置使用共享服务器的共享环境而设置调度程序的数量和类型。可以为该...
  • 为了确保创建安全的环境,Windows 管理员通常需要了解特定用户或用户组对文件、目录、注册表项和 Windows 服务等资源具有种访问权限。AccessChk 能够通过直观的界面和输出快速回答这些问题。AccessEnum 这简单...
  • asp.net知识库

    2015-06-18 08:45:45
    完美的关于请求的目录存在而需要url重写的解决方案! 在C#中实现MSN消息框的功能 XmlHttp实现无刷新三联动ListBox 鼠标放在个连接上,会显示图片(类似tooltip) 使用microsoft.web.ui.webcontrols的TabStrip与...
  • 适合个相同程序代码的线程共享一资源(同线程任务对象可被包装成线程对象),实现解耦操作,代码和线程独立。缺点是实现相对复杂。③实现Callable接口,重写call()方法,并包装成FutureTask对...

空空如也

空空如也

1 2
收藏数 36
精华内容 14
关键字:

多线程不共享哪一类资源