线程中资源(一)

原创 2015年11月19日 16:31:02

  对于单线程来说,因为只有一个实体,所以永远都不需要担心“两个实体同时使用同一个资源会发生什么”这样的问题。
  有了并发就可以同时做多件事情了,但是两个或多个线程彼此互相干涉的问题也就出现了。这就是我们将要讨论的事
  1.不正确地访问资源
  如果几个线程同时读一个资源,此时不会更改资源,这时也不会需要考虑这个资源竞争这个问题。但是一旦涉及到写操作,这便会涉及到竞争资源这个问题,这时也会对读造成影响
  2.解决共享资源竞争
  对于并发工作,你需要某种方式来防止两个任务访问相同的资源,至少在关键阶段不能出现这种情况。
  防止这种冲突的方法就是当资源被一个任务使用时,在其加上锁。第一个访问某项资源的任务必须锁定这项资源,使其他任务在其被解锁之前,就无法访问它,而在其被解锁之时,另一个任务就可以锁定并使用它了。
  共享资源一般是以对象形式存在的内存片段,但也可以是文件,输入/输出端口,或者是打印机。要控制对共享资源的访问,必须把它包装进一个对象。而我们会把它打上标记synchronized,下面是synchronized 的声明方式
  

synchronized void f(){}

  所有对象都自动含有单一的锁。当在对象上调用其任意synchronized 方法的时候,此对象都被加锁,这时该对象上的其他synchronized 方法只有等到前一个方法调用完毕并释放了锁之后才能被调用。
  注意,在使用并发时,将域要设置为private ,否则synchronized 关键字就不能防止其他任务直接访问域。
  一个任务可以多次获得对象锁。如果一个方法在同一个对象上调用了第二个方法,后者又调用了同一对象上的另一个方法,就会发生这种情况。jvm负责跟踪对象被加锁的次数。如果一个对象被解锁,其计数就变为0。在任务(注意这里我们用任务不用线程)第一次给对象加锁的时候,计数变为1。每当这个相同的任务在这个对象上获得锁时,计数都会 递增。显然,只有首页获得了锁的任务才能允许继续获取多个锁。每当任务离开一个synchronized 方法,计数递减,当计数为0的时候锁被完全释放,此时别的任务就可以使用这个资源。
  针对每个类,也有一个锁,synchronized static方法可以在类的范围内防止对static数据的并发访问。
  这个时候就有问题了,你应该什么时候同步呢?,这里要说一下Brain的同步规则:
  

如果你正在写一个变量,它可能接下来将被另一个线程读取,或者正在读取一个上一次已经被另一个线程写过的变量,那么你必须使用同步,并且,读写进程都必须用相同的监视器同步。

  如果在你的类中有超过一个方法正在处理临界数据,那么你必须同步所有相关的方法。如果只同步一个方法,那么其他方法将会随意地忽略这个对象锁,并可以在无任何惩罚的情况下被调用。这是很重要的一点:每个访问临界共享资源的方法都必须被同步,否则它们就不会正确地工作。
  使用显示的Lock对象

    private Lock lock=new ReentrantLock();
    @Override
    public int next() {
        lock.lock();
        try {
            ++currentEvenValue;
            ++currentEvenValue;
            return currentEvenValue;
        } finally {
            lock.unlock();
        }
    }

在这里我们显示的用lock()和unlock()方法,注意惯用顺序:
开始对lock()的调用,然后在try里面做自己的工作,return必须在try子句中出现,以确保unlock()不会过早发生,从而将数据暴露给了第二个任务。
  虽然try-finally所需的代码比synchronized关键字要多,但是这也代表了显示的Lock对象的优点之一。如果在使用synchronized关键字时,某些事物失败了就会抛出一个异常。但是你没有机会去做任何清理工作,以维护系统使其处于良好状态。有了显示的Lock对象,你就可以使用finally子句将系统维护在正确地状态了。
  一般解决特殊问题时,才显示的Lock对象。

版权声明:本文为博主原创文章,未经博主允许不得转载。

C# 中线程资源访问互斥锁

一个加减数值的例子说明问题 using System; using System.Threading; namespace ThreadLockingDemo { class Progra...
  • conquerwave
  • conquerwave
  • 2016年02月28日 22:02
  • 342

【网络模型】一个客户一个线程

一个客户一个子线程,也是阻塞式网络编程,它的初始化要比一个客户一个进程模型开销要小;但是仍适合于长连接,不适合短连接、并发数不大的情况,尤其不适合pthread_create()的开销大于本身服务的情...
  • skyuppour
  • skyuppour
  • 2015年01月28日 17:07
  • 752

多任务处理:一客户一线程

一客户一线程  在一客户一线程(thread-per-client)的服务器中,为每个连接都创建了一个新的线程来处理。服务器循环执行一些任务,在指定端口上侦听连接,反复接收客户端传入的连接请求,并为...
  • undoner
  • undoner
  • 2012年12月23日 09:42
  • 735

多线程资源共享的问题

线程共享,线程同步
  • king624498030
  • king624498030
  • 2015年04月23日 15:34
  • 1810

JAVA基础学习--一个线程加一运算,一个线程做减一运算,多个线程同时交替运行--synchronized

使用synchronized package com.pb.thread.demo5; /**使用synchronized * 一个线程加一运算,一个线程做减法运算,多个线程...
  • ko0491
  • ko0491
  • 2015年09月19日 19:41
  • 1120

如何解决java线程中的资源共享的问题

更多相关的文章的链接:http://www.cnblogs.com/chenssy/p/4701027.html; 1.资源共享问题的产生:由于需要被访问的资源没有被合理地保护起来,所以在多线程都来访...
  • li12412414
  • li12412414
  • 2016年05月18日 21:41
  • 1321

在DLL中使用资源(转)

在DLL中使用资源    现在最常看见的关于DLL的问题就是如何在DLL中使用对话框,这是一个很普遍的关于如何在DLL中使用资源的问题。这里我们从Win32 DLL和MFC DLL两个方面来分析并解决...
  • wangyh76
  • wangyh76
  • 2005年06月03日 12:17
  • 998

Android中资源各种引用方式?,@,@*等等

本文参考于http://www.cnblogs.com/greatverve/archive/2011/12/27/Android-xml.html,
  • zrf1335348191
  • zrf1335348191
  • 2016年10月12日 14:25
  • 720

Android下面第三方类库资源文件的加载

有些第三方类库是基于J2SE开发的,内部有资源文件,如properties,这些文件在dex编译的时候会被过滤掉,导致类读取资源的时候无法访问。 解决办法是用运行时加载第三方类库。 1、用DX打包...
  • dzg1977
  • dzg1977
  • 2014年12月03日 12:41
  • 865

写四个线程,二个加1,二个对一个变量减一

昨天的面试题(天元网络)  两个问题:    1、线程同步--synchronized    2、线程之间如何共享同一个j变量--内部类  [java] view plai...
  • qiu512300471
  • qiu512300471
  • 2014年09月10日 18:35
  • 922
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:线程中资源(一)
举报原因:
原因补充:

(最多只允许输入30个字)