• 2013.7.30 作业


    1.什么是死锁,怎么解决死锁

    产生死锁的必要条件:

    〈1〉互斥条件。即某个资源在一段时间内只能由一个进程占有,不能同时被两个或两个以上的进程占有。这种独占资源如CD-ROM驱动器,打印机等等,必须在占有该资源的进程主动释放它之后,其它进程才能占有该资源。这是由资源本身的属性所决定的。如独木桥就是一种独占资源,两方的人不能同时过桥。

        〈2〉不可抢占条件。进程所获得的资源在未使用完毕之前,资源申请者不能强行地从资源占有者手中夺取资源,而只能由该资源的占有者进程自行释放。如过独木桥的人不能强迫对方后退,也不能非法地将对方推下桥,必须是桥上的人自己过桥后空出桥面(即主动释放占有资源),对方的人才能过桥。

        〈3〉占有且申请条件。进程至少已经占有一个资源,但又申请新的资源;由于该资源已被另外进程占有,此时该进程阻塞;但是,它在等待新资源之时,仍继续占用已占有的资源。还以过独木桥为例,甲乙两人在桥上相遇。甲走过一段桥面(即占有了一些资源),还需要走其余的桥面(申请新的资源),但那部分桥面被乙占有(乙走过一段桥面)。甲过不去,前进不能,又不后退;乙也处于同样的状况。

        〈4〉循环等待条件。存在一个进程等待序列{P1,P2,...,Pn},其中P1等待P2所占有的某一资源,P2等待P3所占有的某一源,......,而Pn等待P1所占有的的某一资源,形成一个进程循环等待环。就像前面的过独木桥问题,甲等待乙占有的桥面,而乙又等待甲占有的桥面,从而彼此循环等待。

      上面我们提到的这四个条件在死锁时会同时发生。也就是说,只要有一个必要条件不满足,则死锁就可以排除。

    死锁的预防:

      前面介绍了死锁发生时的四个必要条件,只要破坏这四个必要条件中的任意一个条件,死锁就不会发生。这就为我们解决死锁问题提供了可能。一般地,解决死锁的方法分为死锁的预防,避免,检测与恢复三种(注意:死锁的检测与恢复是一个方法)。我们将在下面分别加以介绍。

      死锁的预防是保证系统不进入死锁状态的一种策略。它的基本思想是要求进程申请资源时遵循某种协议,从而打破产生死锁的四个必要条件中的一个或几个,保证系统不会进入死锁状态。

       〈1〉打破互斥条件。即允许进程同时访问某些资源。但是,有的资源是不允许被同时访问的,像打印机等等,这是由资源本身的属性所决定的。所以,这种办法并无实用价值。

       〈2〉打破不可抢占条件。即允许进程强行从占有者那里夺取某些资源。就是说,当一个进程已占有了某些资源,它又申请新的资源,但不能立即被满足时,它必须释放所占有的全部资源,以后再重新申请。它所释放的资源可以分配给其它进程。这就相当于该进程占有的资源被隐蔽地强占了。这种预防死锁的方法实现起来困难,会降低系统性能。    

        〈3〉打破占有且申请条件。可以实行资源预先分配策略。即进程在运行前一次性地向系统申请它所需要的全部资源。如果某个进程所需的全部资源得不到满足,则不分配任何资源,此进程暂不运行。只有当系统能够满足当前进程的全部资源需求时,才一次性地将所申请的资源全部分配给该进程。由于运行的进程已占有了它所需的全部资源,所以不会发生占有资源又申请资源的现象,因此不会发生死锁。但是,这种策略也有如下缺点:

    (1)在许多情况下,一个进程在执行之前不可能知道它所需要的全部资源。这是由于进程在执行时是动态的,不可预测的;

    (2)资源利用率低。无论所分资源何时用到,一个进程只有在占有所需的全部资源后才能执行。即使有些资源最后才被该进程用到一次,但该进程在生存期间却一直占有它们,造成长期占着不用的状况。这显然是一种极大的资源浪费;

    (3)降低了进程的并发性。因为资源有限,又加上存在浪费,能分配到所需全部资源的进程个数就必然少了。    

    (4)打破循环等待条件,实行资源有序分配策略。采用这种策略,即把资源事先分类编号,按号分配,使进程在申请,占用资源时不会形成环路。所有进程对资源的请求必须严格按资源序号递增的顺序提出。进程占用了小号资源,才能申请大号资源,就不会产生环路,从而预防了死锁。这种策略与前面的策略相比,资源的利用率和系统吞吐量都有很大提高,但是也存在以下缺点:

    (1)限制了进程对资源的请求,同时给系统中所有资源合理编号也是件困难事,并增加了系统开销;

    (2)为了遵循按编号申请的次序,暂不使用的资源也需要提前申请,从而增加了进程对资源的占用时间。

    2.线程同步有几种实现方法,都是什么?

    临界区、互斥区、事件、信号量四种方式
      临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)、事件(Event)的区别 
      1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。在任意时刻只允许一个线程对共享资源进行访问,如果有多个线程试图访问公共资源,那么在有一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以抢占。 
      2、互斥量:采用互斥对象机制。 只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问。互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享 
      3、信号量:它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目 
      4、事 件: 通过通知操作的方式来保持线程的同步,还可以方便实现对多个线程的优先级比较的操作

    3.C++以及OC单例

    #include <iostream>
    #include <memory>
    using namespace std;
    //最简单的
    class Singleton
    {
    
    public:
        static Singleton *Instance()
        {
            if (0==_instance) {
                _instance=new Singleton;
            }
            return _instance;
        }
        
    protected:
        Singleton(void)
        {
            
        }
        virtual ~Singleton(void)
        {
            
        }
        static Singleton * _instance;
        
    };
    
    //释放内存
    
    class Singleton1 {
        
        
    public:
        static Singleton1 *Instance1()
        {
            if (0==_instance1.get()) {
                _instance1.reset(new Singleton1);
            }
            return _instance1.get();
        }
        
    protected:
        Singleton1(void)
        {
            cout<<"Creat Singleton"<<endl;
        }
        virtual ~Singleton1(void)
        {
            cout<<"Destory Singleton"<<endl;
        }
        friend class auto_ptr<Singleton1>;
        static auto_ptr<Singleton1>_instance1;
    };
    
    #import "File.h"
    
    @implementation File
    
    //定义一个静态实例,并初始化为nill
    static File *sharefile=nil;
    
    +(File*)shareFile
    {
        @synchronized(self)//线程保护
        {
            //如果实例为nil,则创建该实例
            if (sharefile==nil) {
                sharefile=[[self alloc]init];
            }
        }
        return sharefile;
    }
    
    +(id)allocWithZone:(NSZone *)zone
    {
        NSLog(@"nil %p");
        @synchronized(self){
            if (sharefile==nil) {
                sharefile=[super allocWithZone:zone];
                return sharefile;
            }
        }
        return sharefile;
    }
    
    //覆盖allocWirhZone方法
    -(id)copyWithZone:(NSZone*)zone
    {
        return self;//实现copy协议,返回本身
    }
    
    -(id)retain
    {
        return self;//返回本身
    }
    
    -(NSInteger)retainCount
    {
        return UINT_MAX;//返回无符号整形范围最大值
    }
    -(oneway void)release
    {
        //什么都不做
    }
    -(id)autorelease
    {
        return self;//返回本身
    }
    @end
    

      

    4.游乐场有3条游客入场通道,但是最多只能容纳150人。请使用多线程的方式实现这个场景!

    //.h
    #import <Foundation/Foundation.h>
    
    @interface SwimAdminAppDelegate : NSObject
    {
        int count;
        int rest;
        NSThread *thread1;
        NSThread *thread2;
        NSThread *thread3;
        NSCondition *condation;
    }
    
    @property int count;
    @property int rest;
    
    -(void)fun1;
    -(void)swim;
    @end
    
    
    //.m
    #import "SwimAdminAppDelegate.h"
    
    @implementation SwimAdminAppDelegate
    @synthesize count;
    @synthesize rest;
    
    -(void)fun1
    {
        count=0;
        rest=150;
        
        condation=[[NSCondition alloc]init];
        thread1=[[NSThread alloc]initWithTarget:self selector:@selector(swim) object:nil];
        [thread1 setName:@"thread1"];
        [thread1 start];
        thread2=[[NSThread alloc]initWithTarget:self selector:@selector(swim) object:nil];
        [thread2 setName:@"thread2"];
        [thread2 start];
        thread3=[[NSThread alloc]initWithTarget:self selector:@selector(swim) object:nil];
        [thread3 setName:@"thread3"];
        [thread3 start];
        
    }
    -(void)swim
    {
        while (TRUE) {
            [condation lock];
            if(rest>0)
            {
                NSLog(@"现在还有余票:%d张,售出:%d张 线程:%@ ",rest,count,[[NSThread currentThread]name]);
                rest--;
                count=150-rest;
            }
          else
          {
              break;
          }
            [condation unlock];
        }
    }
    @end
    
    //main()
    #import <Foundation/Foundation.h>
    #import "SwimAdminAppDelegate.h"
    
    int main(int argc, const char * argv[])
    {
    
        @autoreleasepool {
            
            NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init];
            SwimAdminAppDelegate *swimer=[[SwimAdminAppDelegate alloc]init];
            [swimer fun1];
            [NSThread sleepForTimeInterval:10];
            
        }
        return 0;
    }
    

      

    5.写出一个异常程序,并捕获它。

    //Cup.h
    #import <Foundation/Foundation.h>
    #import "CupOverFlowException.h"
    #import "CupWarningException.h"
    
    @interface Cup : NSObject
    {
        int level; //成员变量,水的深度值
    }
    //获取水的深度值
    -(int)level;
    
    //设置水的深度值
    -(void)setLevel:(int)i;
    
    //水的深度值加10
    -(void)fill;
    
    //水的深度值减10
    -(void)empty;
    
    //输出水的深度值
    -(void)print;
    
    //计算一个百分比
    -(double)set:(double)a over :(double)b;
    
    @end
    
    //Cup.m
    #import "Cup.h"
    
    
    @implementation Cup
    
    -(id)init
    {
        if (self=[super init]) {
            [self setLevel:0];
        }
        return self;
    }
    
    -(int)level
    {
        return level;
    }
    
    -(void)setLevel:(int)i
    {
        level=i;
        if (level>100) {
            NSException *e=[CupOverFlowException exceptionWithName:@"CupOverFlowException" reason:@"the level is above 100" userInfo:nil];
            @throw e;
        }
        else if (level>=50)
        {
            NSException *e=[CupWarningException exceptionWithName:@"CupWarningException" reason:@"the level is above or at 50" userInfo:nil];
            @throw e ;//抛出异常警告
        }
        else if(level<0)
        {
            NSException *e=[NSException exceptionWithName:@"CupUnderflowException" reason:@"the level is below 0" userInfo:nil];
            @throw e;
        }
    }
    
    -(void)fill
    {
        [self setLevel:level+10];
    }
    -(void)empty
    {
        [self setLevel:level-10];
    
    }
    
    -(void)print
    {
        NSLog(@"the level is %d",level);
    }
    
    -(double)set:(double)a over:(double)b
    {
        return a/b;
    }
    @end
    
    
    
    //CupWarningException.h
    #import <Foundation/Foundation.h>
    
    @interface CupWarningException : NSException
    
    @end
    //CupWarningException.m
    #import "CupWarningException.h"
    
    @implementation CupWarningException
    
    @end
    
    
    // CupOverFlowException.h
    #import <Foundation/Foundation.h>
    
    @interface CupOverFlowException : NSException
    
    @end
    // CupOverFlowException.m
    #import "CupOverFlowException.h"
    
    @implementation CupOverFlowException
    
    @end
    
    
    //main
    #import <Foundation/Foundation.h>
    #import <Foundation/NSString.h>
    #import <Foundation/NSException.h>
    #import <Foundation/NSAutoreleasePool.h>
    #import "Cup.h"
    #import "CupWarningException.h"
    #import "CupOverFlowException.h"
    
    
    int main(int argc, const char * argv[])
    {
    
        @autoreleasepool {
            NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init];
        
            Cup *cup=[[Cup alloc]init];
            int i=0;
            for (i=0; i<4; i++) {
                [cup fill];
                [cup print];
            }
            
            for (i=0; i<7; i++) {
                @try {
                    [cup fill];
                }
                @catch (CupWarningException *e) {
                    NSLog(@"%@ %@",[e name],[e reason]);
                }
                @catch (CupOverFlowException *e) {
                    NSLog(@"%@ %@",[e name],[e reason]);
                }
                @finally {
                    [cup print];
                }
            }
    
            @try {
                [cup setLevel:-1];
            }
            @catch (NSException *e) {
                NSLog(@"%@ %@",[e name],[e reason]);
            }
        
            
        }
        return 0;
    }
    

      

     

     

  • 相关阅读:
    解决maven构建webapp index.jsp报错问题
    Maven入门介绍
    Linux常用命令的解释
    linux怎么查看一个文件夹的大小
    EPEL源-是什么全称
    nginx+php-fpm配置后页面显示空白的解决方法(yum形式的安装)
    配置新服务器 的一些 依赖库 php mysql nginx
    服务器 CentOS上yum安装Nginx服务
    Java File创建新目录和文件
    struts2的文件上传
  • 原文地址:https://www.cnblogs.com/ymonke/p/3227513.html
Copyright © 2020-2023  润新知