精华内容
下载资源
问答
  • 爬虫爬取页面过程中HttpClient导致进程阻塞问题目前在做爬虫项目,爬取多个书籍网站书籍详情页面,遇到一个很恶心问题,别网站都能在短时间内完成爬取,唯独网站A线程卡死,永远随机阻塞在某个页面。...

    爬虫爬取页面过程中HttpClient导致进程阻塞问题

    目前在做爬虫项目,爬取多个书籍网站的书籍详情页面,遇到一个很恶心的问题,别的网站都能在短时间内完成爬取,唯独网站A的线程卡死,永远随机的阻塞在某个页面。定位到错误点在下载函数,这是初始的下载函数:


    public String staticDownload(String urlstr, String encoding,String param) throws Exception{
    StringBuffer buffer = new StringBuffer();
    URL url = null;
    PrintWriter out = null;
    BufferedReader in = null;
    try {
      url = new URL(urlstr);
      URLConnection connection = url.openConnection();
      ((HttpURLConnection) connection).setRequestMethod("POST");
      connection.setDoOutput(true);
      connection.setDoInput(true);
      connection.setConnectTimeout(5000);
      connection.setReadTimeout(5000);
      connection.setRequestProperty("accept", "*/*");
      connection.setRequestProperty("connection", "Keep-Alive");
      connection.setRequestProperty("User-Agent", "Mozilla/5.0 "
          + "(Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.14) "
          + "Gecko/20080404 Firefox/2.0.0.14");
      out = new PrintWriter(connection.getOutputStream());
      // 发送请求参数
      out.print(param);
      // flush输出流的缓冲
      out.flush();
      in = new BufferedReader(new     InputStreamReader(connection.getInputStream(), encoding));
      String line;
      while ((line = in.readLine()) != null) {
        buffer.append(line);
        buffer.append("\r\n");
      }
    }
        catch (Exception e) {
      // TODO: handle exception
        }
        finally{
           try{
                  if(out!=null){
                      out.close();
                  }
                  if(in!=null){
                      in.close();
                  }
              }
              catch(IOException ex){
                  ex.printStackTrace();
              }
        }
    return buffer.toString();
    }       
    

    这里延伸一下,页面下载方式有很多种,如果是爬虫,最好是模拟浏览器行为下载页面,使用WebClient方法,但对于需要人行为参与的页面,比如网站的搜索页面,需要填入搜索项进而获得爬取的内容,我们知道向指定网站发出请求的方式有两种:getpost方式。

    基于HTTP 协议来访问网络资源的URLconnection 和HttpClient均可以实现上述请求,贴上两者区别的地址,具体不做分析。显然我们这里用的是前者。

    通过查找资料 知道readline()是一个阻塞函数,当没有数据读取时就会一直卡在那里:

    • 1、只有当数据流出现异常或者网站服务端主动close()掉时才会返回null值,

    • 2、如果不指定buffer的大小,则readLine()使用的buffer有8192个字符。在达到buffer大小之前,只有遇到“/r”、”/n”、”/r/n”才会返回。

    我们不知道所爬取的网站服务端返回的是否有内容,为空数据也会阻塞,如果有内容每一行内容到底有没有包含以上三个特殊字符,如果不包含,则会进入阻塞,也就说while循环无法跳出,真正的问题找到了,那么只能换掉readline()了,资料也建议socket流最好避免使用readline()函数。

    既然URLConnection不行那就换成HttpClient吧,后者比前者更为强大,也不需要readline()函数,反正病急乱投医喽,我们的问题出现在以post方式获得页面的函数上,param为传入的值,再次运行爬虫问题定位到:


    public String staticDownloadByHttpClient(String urlstr, String encoding, boolean bFrame, String param) throws IOException {
    String bufferStr= null;
    // 创建默认的httpClient实例.
    CloseableHttpClient httpclient = HttpClients.createDefault();
    // 创建httppost
    HttpPost httppost = new HttpPost(urlstr);
    // 创建参数队列
    List<NameValuePair> formparams = new ArrayList<NameValuePair>();
    String name = param.split("=")[0];
    String value = param.split("=")[1];
    formparams.add(new BasicNameValuePair(name, value));
    UrlEncodedFormEntity uefEntity;
    try {
      uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
      httppost.setEntity(uefEntity);
    
      CloseableHttpResponse response = httpclient.execute(httppost);
      if (response == null) {
        httpclient.close();
        return  bufferStr;
      }
      try {
        HttpEntity entity = response.getEntity();
        if (entity != null) {
          InputStream is = entity.getContent();
          InputStreamReader in = new InputStreamReader(is, encoding);
          int ch = 0;
          //貌似这条if语句没啥用,当时主要怕网站返回数据为空
          if((ch = in.read())!=-1){
            //问题出现下面这条语句上
            bufferStr = EntityUtils.toString(entity, encoding);
          }
          else{
            try {
              Thread.sleep(sleepTime);
            } catch (InterruptedException e) {
                e.printStackTrace()
            }
          }
        }
        try {
          EntityUtils.consume(entity);
        } catch (final IOException ignore) {
        }
    
      } finally {
        response.close();
      }
    } catch (ClientProtocolException e) {
        e.printStackTrace()
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace()
    } catch (IOException e) {
        e.printStackTrace()
    } finally {
      // 关闭连接,释放资源
      try {
        httpclient.close();
      } catch (IOException e) {
          e.printStackTrace()
      }
    }
    return  bufferStr;
    }   
    

    无奈只能去查看toSting函数源代码,该代码我有微小改动,基本是这样的:


    private String toString(final HttpEntity entity, final Charset defaultCharset) throws IOException, ParseException {
          Args.notNull(entity, "Entity");
          final InputStream instream = entity.getContent();
          if (instream == null) {
              return null;
          }
          try {
              Args.check(entity.getContentLength() <= Integer.MAX_VALUE,
                      "HTTP entity too large to be buffered in memory");
              int i = (int)entity.getContentLength();
              if (i < 0) {
                  i = 4096;
              }
              Charset charset = null;
              try {
                  final ContentType contentType = ContentType.get(entity);
                  if (contentType != null) {
                      charset = contentType.getCharset();
                  }
              } catch (final UnsupportedCharsetException ex) {
                  throw new UnsupportedEncodingException(ex.getMessage());
              }
              if (charset == null) {
                  charset = defaultCharset;
              }
              if (charset == null) {
                  charset = HTTP.DEF_CONTENT_CHARSET;
              }
              final Reader reader = new InputStreamReader(instream, charset);
              final CharArrayBuffer buffer = new CharArrayBuffer(i);
              final char[] tmp = new char[1024];
              int l;
              long dis = System.currentTimeMillis();
              //问题依旧在这里
              while(reader.ready() && (l = reader.read(tmp)) != -1 ) {
                  buffer.append(tmp, 0, l);
                  long now = System.currentTimeMillis();
                  if(now-dis > 5*60*1000){
                    logUtil.getLogger().error(String.format("MSG: the content that site return is too large to be buffered in memory, 超时: %s ms", now-dis));
                    break;
                  }
              }
              return buffer.toString();
          } finally {
              instream.close();
          }
      }
      private String toString(final HttpEntity entity, final String defaultCharset) throws IOException, ParseException {
        return toString(entity, defaultCharset != null ?        Charset.forName(defaultCharset) : null);
    }  
    

    继续定位问题,呵呵,依旧是while死循环问题,这里显然是同样的一个字符一个字符读入的,不存在readline函数问题,绝望之下百度了“HttpClient post 超时处理“,看到了此大神的很短的一篇日志,其中一句话是:
    BTW,4.3版本不设置超时的话,一旦服务器没有响应,等待时间N久(>24小时)

    又看了看我的HttpClient jar包版本,墙裂感觉问题要被解决了,于是立刻加上超时设置:

    RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(6000).setConnectTimeout(6000).build();//设置请求和传输超时时间
    httppost.setConfig(requestConfig);

    目前已测试8+遍,都没有出现线程再卡死的情况,后来想想,对于这种涉及到socket编程不都应该加上超时处理么,来,跟我读一遍以下文字:

    我们知道Socket在读数据的时候是阻塞式的,如果没有读到数据程序会一直阻塞在那里。在同步请求的时候我们肯定是不能允许这样的情况发生的,这就需要我们在请求达到一定的时间后控制阻塞的中断,让程序得以继续运行。Socket为我们提供了一个setSoTimeout()方法来设置接收数据的超时时间,单位是毫秒。当设置的超时时间大于0,并且超过了这一时间Socket还没有接收到返回的数据的话,Socket就会抛出一个SocketTimeoutException

    参考:
    http://blog.csdn.net/hguang_zjh/article/details/33743249
    http://blog.csdn.net/wuhong_csdn/article/details/50830349
    http://witcheryne.iteye.com/blog/1135817
    http://www.yiibai.com/java/io/bufferedreader_ready.html
    https://zhidao.baidu.com/question/330258186.html
    https://my.oschina.net/u/577453/blog/173724
    http://elim.iteye.com/blog/1979837

    展开全文
  • 3.1 工作队列3.2 等待队列3.3 唤醒进程3.4 内核接收网络数据全过程3.5 进程阻塞为什么不消耗CPU? 进程如何阻塞?进程阻塞为什么不消耗CPU? 要想明白进程如何阻塞,阻塞为什么不消耗CPU,就要先明白 计算机是如何...

    进程如何阻塞?进程阻塞为什么不消耗CPU?

    要想明白进程如何阻塞,阻塞为什么不消耗CPU,就要先明白

    • 计算机是如何接受数据的
    • 计算机如何知道什么时候要接收数据

    1. 计算机是如何接收数据的

    从网卡接收数据说起:

    下边是一个典型的计算机结构图,计算机由 CPU、存储器(内存)与网络接口等部件组成,先从硬件的角度看计算机怎样接收网络数据。

    在这里插入图片描述
    下图展示了网卡接收数据的过程:

    • 在 1 阶段,网卡收到网线传来的数据。
    • 经过 2 阶段的硬件电路的传输。
    • 最终 3 阶段将数据写入到内存中的某个地址上。

    这个过程涉及到 DMA 传输、IO 通路选择等硬件有关的知识,但我们只需知道:网卡会把接收到的数据写入内存。

    在这里插入图片描述
    网卡接收数据的过程:
    通过硬件传输,网卡接收的数据存放到内存中,操作系统就可以去读取它们。

    2. 计算机如何知道要接受数据?

    答:中断

    • 计算机执行程序时,会有优先级的需求。比如,当计算机收到断电信号时,它应立即去保存数据,保存数据的程序具有较高的优先级(电容可以保存少许电量,供 CPU 运行很短的一小段时间)。
    • 一般而言,由硬件产生的信号需要 CPU 立马做出回应,不然数据可能就丢失了,所以它的优先级很高。
    • CPU 理应中断掉正在执行的程序,去做出响应;当 CPU 完成对硬件的响应后,再重新执行用户程序。

    中断的过程如下图,它和函数调用差不多,只不过函数调用是事先定好位置,而中断的位置由“信号”决定。

    在这里插入图片描述

    中断程序调用

    以键盘为例,当用户按下键盘某个按键时,键盘会给 CPU 的中断引脚发出一个高电平,CPU 能够捕获这个信号,然后执行键盘中断程序。

    下图展示了各种硬件通过中断与 CPU 交互的过程:
    在这里插入图片描述
    现在可以回答“如何知道接收了数据?”这个问题了:当网卡把数据写入到内存后,网卡向 CPU 发出一个中断信号,操作系统便能得知有新数据到来,再通过网卡中断程序去处理数据。

    3. 进程阻塞为什么不占用 CPU 资源?

    从操作系统进程调度的角度来看数据接收。阻塞是进程调度的关键一环,指的是进程在等待某事件(如接收到网络数据)发生之前的等待状态,Recv、Select 和 Epoll 都是阻塞方法。

    下边分析一下进程阻塞为什么不占用 CPU 资源?为简单起见,我们从普通的 Recv 接收开始分析,先看看下面代码:

    //创建socket 
    int s = socket(AF_INET, SOCK_STREAM, 0);    
    //绑定 
    bind(s, ...) 
    //监听 
    listen(s, ...) 
    //接受客户端连接 
    int c = accept(s, ...) 
    //接收客户端数据 
    recv(c, ...); 
    //将数据打印出来 
    printf(...) 
    

    这是一段最基础的网络编程代码,先新建 Socket 对象,依次调用 Bind、Listen 与 Accept,最后调用 Recv 接收数据。

    Recv 是个阻塞方法,当程序运行到 Recv 时,它会一直等待,直到接收到数据才往下执行。那么阻塞的原理是什么?

    3.1 工作队列

    操作系统为了支持多任务,实现了进程调度的功能,会把进程分为“运行”和“等待”等几种状态。

    运行状态是进程获得 CPU 使用权,正在执行代码的状态;等待状态是阻塞状态,比如上述程序运行到 Recv 时,程序会从运行状态变为等待状态,接收到数据后又变回运行状态。

    操作系统会分时执行各个运行状态的进程,由于速度很快,看上去就像是同时执行多个任务。

    下图的计算机中运行着 A、B 与 C 三个进程,其中进程 A 执行着上述基础网络程序,一开始,这 3 个进程都被操作系统的工作队列所引用,处于运行状态,会分时执行。

    在这里插入图片描述
    工作队列中有 A、B 和 C 三个进程

    3.2 等待队列

    当进程 A 执行到创建 Socket 的语句时,操作系统会创建一个由文件系统管理的 Socket 对象(如下图)。

    在这里插入图片描述

    创建 Socket

    这个 Socket 对象包含了发送缓冲区、接收缓冲区与等待队列等成员。等待队列是个非常重要的结构,它指向所有需要等待该 Socket 事件的进程。

    当程序执行到 Recv 时,操作系统会将进程 A 从工作队列移动到该 Socket 的等待队列中(如下图)。

    在这里插入图片描述
    Socket 的等待队列

    由于工作队列只剩下了进程 B 和 C,依据进程调度,CPU 会轮流执行这两个进程的程序,不会执行进程 A 的程序。所以进程 A 被阻塞,不会往下执行代码,也不会占用 CPU 资源。

    注:操作系统添加等待队列只是添加了对这个“等待中”进程的引用,以便在接收到数据时获取进程对象、将其唤醒,而非直接将进程管理纳入自己之下。上图为了方便说明,直接将进程挂到等待队列之下。

    3.3 唤醒进程

    当 Socket 接收到数据后,操作系统将该 Socket 等待队列上的进程重新放回到工作队列,该进程变成运行状态,继续执行代码。

    同时由于 Socket 的接收缓冲区已经有了数据,Recv 可以返回接收到的数据。

    3.4 内核接收网络数据全过程

    这一步,贯穿网卡、中断与进程调度的知识,叙述阻塞 Recv 下,内核接收数据的全过程。
    在这里插入图片描述
    内核接收数据全过程

    如上图所示,进程在 Recv 阻塞期间:

    • 计算机收到了对端传送的数据(步骤 ①)
    • 数据经由网卡传送到内存(步骤 ②)
    • 然后网卡通过中断信号通知 CPU 有数据到达,CPU 执行中断程序(步骤 ③)

    此处的中断程序主要有两项功能,先将网络数据写入到对应 Socket 的接收缓冲区里面(步骤 ④),再唤醒进程 A(步骤 ⑤),重新将进程 A 放入工作队列中。

    唤醒进程的过程如下图所示:
    在这里插入图片描述

    3.5 进程阻塞为什么不消耗CPU?

    答:进程执行的过程的确是在内核CPU中执行的,会消耗CPU。但是当进程阻塞变成等待态的时候,会被加入该socket的等待队列中,并不会出现在内核中了,而是在socket的等待队列中“等待”。当进程被操作系统唤醒后,又会被加入到工作队列中。

    展开全文
  • 问题 ...参考Electron进程阻塞导致UI卡顿问题这篇文章,我大概了解了electron渲染方式: 实际原因正是和其中IPC有关,在chromium中,页面渲染时,UI进程需要和main process不断进行syn

    问题

    在使用electron的过程中可能会出现这样的问题:

    在我回调一个方法,比如child_process.spawn()的时候,我设计的等待动画不会出问题,在计算结束后等待动画也会结束,但是当我使用child_process.spawn()时就会出现动画进程不进行的情况。

    参考Electron的主进程阻塞导致UI卡顿的问题这篇文章,我大概了解了electron的渲染方式:

    实际的原因正是和其中的IPC有关,在chromium中,页面渲染时,UI进程需要和main process不断的进行sync IPC,若此时main process忙,则UI process就会在IPC时阻塞。

    由于js是单线程的,在执行函数时如果遇到重cpu任务时就会造成主进程阻塞的情况。

     解决方法

    那么该如何解决呢?我们可能会想既然异步的回调不会造成阻塞,为什么我们不都使用异步呢?

    当接口是回调函数的时候当然没有问题,但是有些函数提供的api是同步的,如何解决这个问题?

    这时候我们可以使用electron提供的window窗口功能,在需要执行的时候提前创建好一个透明窗口用来执行重cpu任务。当执行完成的时候通过ipc进行进程的通讯。

    举个栗子:

    //demo.js
    function click() {
        const windowID = BrowserWindow.getFocusedWindow().id
        const invisPath = 'remote.html'
        let win = new BrowserWindow({
            width: 400,
            height: 400,
            show: false,
            webPreferences: {
                nodeIntegration: true
            }
        })
        win.loadFile(invisPath);
    
        win.webContents.on('did-finish-load', () => {
            var par;
            win.webContents.send('compute-vis', par, windowID);
        })
    });
    
    ipcRenderer.on('vis-computed', (event, output) => {
        console.log(output);
    })
    <!--remote.html-->
    <html>
    <script type="text/javascript">
        const ipc = require('electron').ipcRenderer
        const BrowserWindow = require('electron').remote.BrowserWindow
        const child_process = require('child_process');
    
        ipc.on('compute-vis', function (event, par, fromWindowId) {
            const result = visBuilding(par)
            const fromWindow = BrowserWindow.fromId(fromWindowId)
            fromWindow.webContents.send('vis-computed', result)
            window.close()
        })
    
        function visBuilding(par) {
            return par;
        }
    
    </script>
    
    </html>

     其中加载html的方法有两种:

    mainWindow.loadURL(url.format({
      pathname: path.join(__dirname, 'index.html'),
      protocol: 'file:',
      slashes: true
    }));
    // or
    invisPath=path.join(__dirname, 'index.html');
    mainWindow.loadFile(invisPath);
    

    这样就可以在子窗口中进行计算,并且回调结果了~

    展开全文
  • UPDLOCK 优点是允许您读取数据(不阻塞其它事务)并在以后更新数据,同时确保自从上次读取数据后数据没有被更改。  这是SqlServer2000中对更新锁说明.  当我们用UPDLOCK来读取记录时可以对取到记录加上更新...

    use master
    go
    alter procedure sp_who_lock
    as
    begin
    declare @spid int,@bl int,
    @intTransactionCountOnEntry int,
    @intRowcount int,
    @intCountProperties int,
    @intCounter int

    create table #tmp_lock_who (
    id int identity(1,1),
    spid smallint,
    bl smallint)

    IF @@ERROR<>0 RETURN @@ERROR

    insert into #tmp_lock_who(spid,bl) select 0 ,blocked
    from (select * from sysprocesses where blocked>0 ) a
    where not exists(select * from
    (select * from sysprocesses where blocked>0 ) b
    where a.blocked=spid)
    union select spid,blocked from sysprocesses where blocked>0

    IF @@ERROR<>0 RETURN @@ERROR

    -- 找到临时表的记录数
    select @intCountProperties = Count(*),@intCounter = 1
    from #tmp_lock_who

    IF @@ERROR<>0 RETURN @@ERROR

    if @intCountProperties=0
    select '现在没有阻塞和死锁信息' as message

    -- 循环开始
    while @intCounter <= @intCountProperties begin
    -- 取第一条记录
    select @spid = spid,@bl = bl
    from #tmp_lock_who where Id = @intCounter
    if @spid =0 begin
    select '引起数据库死锁的是: '+ CAST(@bl AS VARCHAR(10))
    + '进程号,其执行的SQL语法如下'
    end
    else begin
    select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))+ '被'
    + '进程号SPID:'+ CAST(@bl AS VARCHAR(10)) +'阻塞,其当
    前进程执行的SQL语法如下'DBCC INPUTBUFFER (@bl )
    end
    end
    end


    --exec sp_who_lock


    create table #t(req_spid int,obj_name sysname)

    declare @s nvarchar(4000)
    ,@rid int,@dbname sysname,@id int,@objname sysname

    declare tb cursor for
    select distinct req_spid,dbname=db_name(rsc_dbid),rsc_objid
    from master..syslockinfo where rsc_type in(4,5)
    open tb
    fetch next from tb into @rid,@dbname,@id
    while @@fetch_status=0
    begin
    set @s='select @objname=name from ['+@dbname+']..sysobjects where id=@id'
    exec sp_executesql @s,N'@objname sysname out,@id int',@objname out,@id
    insert into #t values(@rid,@objname)
    fetch next from tb into @rid,@dbname,@id
    end
    close tb
    deallocate tb

    select 进程id=a.req_spid
    ,数据库=db_name(rsc_dbid)
    ,类型=case rsc_type when 1 then 'NULL 资源(未使用)'
    when 2 then '数据库'
    when 3 then '文件'
    when 4 then '索引'
    when 5 then '表'
    when 6 then '页'
    when 7 then '键'
    when 8 then '扩展盘区'
    when 9 then 'RID(行 ID)'
    when 10 then '应用程序'
    end
    ,对象id=rsc_objid
    ,对象名=b.obj_name
    ,rsc_indid
    from master..syslockinfo a left join #t b on a.req_spid=b.req_spid

    go
    drop table #t


    数据库的表锁定是一个常用的操作,SQL语句中的锁定语句应该如何书写呢?下面就将为您详细介绍SQL语句中的锁定语句的用法。

    锁定数据库的一个表

    SELECT * FROM table WITH (HOLDLOCK)

    注意: 锁定数据库的一个表的区别

    SELECT * FROM table WITH (HOLDLOCK)

    其他事务可以读取表,但不能更新删除

    SELECT * FROM table WITH (TABLOCKX)

    其他事务不能读取表,更新和删除

    SELECT 语句中“加锁选项”的功能说明

    SQL Server提供了强大而完备的锁机制来帮助实现数据库系统的并发性和高性能。用户既能使用SQL Server的缺省设置也可以在select 语句中使用“加锁选项”来实现预期的效果。 本文介绍了SELECT语句中的各项“加锁选项”以及相应的功能说明。

    功能说明: 

    NOLOCK(不加锁)

    此选项被选中时,SQL Server 在读取或修改数据时不加任何锁。 在这种情况下,用户有可能读取到未完成事务(Uncommited Transaction)或回滚(Roll Back)中的数据, 即所谓的“脏数据”。

    HOLDLOCK(保持锁)

    此选项被选中时,SQL Server 会将此共享锁保持至整个事务结束,而不会在途中释放。

    UPDLOCK(修改锁)

    此选项被选中时,SQL Server 在读取数据时使用修改锁来代替共享锁,并将此锁保持至整个事务或命令结束。使用此选项能够保证多个进程能同时读取数据但只有该进程能修改数据。

    TABLOCK(表锁)
    UPDLOCK

      读取表时使用更新锁,而不使用共享锁,并将锁一直保留到语句或事务的结束。UPDLOCK 的优点是允许您读取数据(不阻塞其它事务)并在以后更新数据,同时确保自从上次读取数据后数据没有被更改。

      这是SqlServer2000中对更新锁的说明.

      当我们用UPDLOCK来读取记录时可以对取到的记录加上更新锁,从而加上锁的记录在其它的线程中是不能更改的只能等本线程的事务结束后才能更改,我如下示例:

    BEGIN TRANSACTION --开始一个事务
    SELECT Qty
    FROM myTable WITH (UPDLOCK)
    WHERE Id in (1,2,3)

    UPDATE myTable SET Qty = Qty - A.Qty
    FROM myTable AS A
    INNER JOIN @_Table AS B ON A.ID = B.ID

    COMMIT TRANSACTION --提交事务

      这样在更新时其它的线程或事务在这些语句执行完成前是不能更改ID是1,2,3的记录的.其它的都可以修改和读,1,2,3的只能读,要是修改的话只能等这些语句完成后才能操作.从而保证的数据的修改正确.
      
      
      
      
      此选项被选中时,SQL Server 将在整个表上置共享锁直至该命令结束。 这个选项保证其他进程只能读取而不能修改数据。

    PAGLOCK(页锁)

    此选项为默认选项, 当被选中时,SQL Server 使用共享页锁。

    TABLOCKX(排它表锁)

    此选项被选中时,SQL Server 将在整个表上置排它锁直至该命令或事务结束。这将防止其他进程读取或修改表中的数据。


    HOLDLOCK 持有共享锁,直到整个事务完成,应该在被锁对象不需要时立即释放,等于SERIALIZABLE事务隔离级别

    NOLOCK 语句执行时不发出共享锁,允许脏读 ,等于 READ UNCOMMITTED事务隔离级别

    PAGLOCK 在使用一个表锁的地方用多个页锁

    READPAST 让sql server跳过任何锁定行,执行事务,适用于READ UNCOMMITTED事务隔离级别只跳过RID锁,不跳过页,区域和表锁

    ROWLOCK 强制使用行锁

    TABLOCKX 强制使用独占表级锁,这个锁在事务期间阻止任何其他事务使用这个表

    UPLOCK 强制在读表时使用更新而不用共享锁

    注意: 锁定数据库的一个表的区别

    SELECT * FROM table WITH (HOLDLOCK) 其他事务可以读取表,但不能更新删除

    SELECT * FROM table WITH (TABLOCKX) 其他事务不能读取表,更新和删除[code="java"]

    [/code]
    展开全文
  • 本篇是多路复用相关的知识的第二篇文章,主要讲解中断和进程阻塞在整个网络数据传递过程中,所经历的过程。一、中断一般而言,由硬件产生的信号需要cpu立马做出回应(不然数据可能就丢失),所以它...
  • 进程阻塞

    2021-03-26 17:54:07
    进程 :程序关于某个数据集合一次执行过程进程的特征 :进程控制块(pcb)+程序+数据=进程实体 程序:程序是一组有序指令集合,是静态概念 进程有 动态性,并发性,独立性 ,异步性 进程的三种基本状态 :...
  • 同步: 访问数据的方式,同步需要主动读写数据,在读写数据的过程中还是会阻塞;  2.异步: 异步只需要I/O操作完成的通知,并不主动读写数据,由操作系统内核完成数据的读写。 阻塞阻塞是针对某次系统调用而言, ...
  • 我先创建一个进程池,用主进程处理socket,accept接收到一个连接请求,成功后将其返回值传入结构体链表用子进程处理,在子进程处理过程中我进程还处于阻塞状态吗?还是去等待新连接了?
  • 进程阻塞解决方案

    千次阅读 2018-05-10 14:36:32
    毕设做了个可视化界面,用来展示我仿真过程,做起来一波三折啊。记录一下用Runtime.getRuntime().exec(s)时出现问题。2018年5月10日13:44:54一、执行一些比较复杂语句时无法执行,直接退出来解决方法:在...
  • 进程挂起是由于I/o跟不上处理器速度,I/o已被占用,那么下一个请示I/o的进程阻塞,如此如此,当就绪队列中没有进程时(全部阻塞),则挂起某个阻塞进程一部分或全部内容(这句话可能有问题,是摘抄) ...
  • 就需要有创建进程的方式,一些操作系统只为一个应用程序设计,比如微波炉中控制器,一旦启动微波炉,所有的进程都已经存在.e而对于通用系统(跑很多应用程序),需要有系统运行过程中创建或撤销进程的能力,主要分为4种...
  • //出问题地方,没有阻塞效果   if ( res >  0  )//有内容情况  {   ...  }   else // keep try open //没有内容情况 ,无奈地睡了一下  {  sleep( 1 ); // need to sleep for a few ...
  • 进程的挂起与阻塞

    千次阅读 2013-06-13 21:39:11
    今天碰到一个问题,解决过程中出现了这样一个疑问:挂起与阻塞有何区别?   搜罗了一些论坛里说法,结合操作系统书上写,得到如下结论:   阻塞是由于进程所需资源得不到满足,并会最终导致进程被挂起 ...
  • 要说挂起、阻塞、睡眠难免让人想到进程生命周期中的阻塞态或者等待状态,而挂起和睡眠却...先说阻塞,既然它能出现在进程生命周期,必然是每个进程都会经历一个阶段,众所周知,进程在运行过程中必然要获取资源,...
  • Python之进程 进程 ...二 什么是进程 ...三 进程调度 ...五 同步\异步\阻塞\非阻塞 ...六 进程的创建与结束 ...八 进程池和mutiprocess.Poll ... 顾名思义,进程即正在执行一个过程进程是对正在运...
  • 开发过程中遇到调用外部 exe 文件过很久才能显示出来,除非是把本身程序终止,调用 exe 文件则很快可以显示,以下是代码部分: Runtime rn = Runtime.getRuntime(); Process p = null;
  • 当需要创建进程数量不多时,可以直接利用multiprocessing中Process动态成生多个进程,但如果是上百甚至上千个目标,手动去创建过程的工作量巨大,此时就可以用到multiprocessing模块提供Pool方法。...
  • 进程是一个正在运行程序,进程是用来描述程序执行过程的虚拟概念 进程的概念起源于操作系统,进程是操作系统最核心概念,操作系统其它所有概念都是围绕进程 2.操作系统 操作系统是一个协调/管理/...
  • 进程的阻塞、唤醒、挂起、激活

    万次阅读 2015-05-07 15:07:14
    进程控制一些概念: 进程控制是进程管理中最基本功能。创建、终止、可负责进程运行中状态转换。 进程控制一般是由OS内核中原语来实现。 原语(Primitive)是由若干条指令组成,用于完成一定功能...
  •  进程控制一般是由OS内核中原语来实现。  原语(Primitive)是由若干条指令组成,用于完成一定功能一个过程。  它与一般过程的区别在于:它们是“原子操作(Action Operation)”。即不可分割、不允
  • 我用java调用mencoder实施转码,但是转码过程中出现子进程阻塞,而且还是看了API才知道这个问题。因为mencoder 控制台输出信息很多,把缓存区所有空间占满了,所以程序不能执行后面程序,mencoder就只能...
  • 同步,异步:访问数据的方式,同步需要主动读写数据,在读写数据的过程中还是会阻塞;异步只需要I/O操作完成的通知,并不主动读写数据,由操作系统内核完成数据的读写。 阻塞阻塞是针对某次系统调用而言,而同步...
  • 今天调用mencoder时遇到 Cannot run program " mencoder"...我用java调用mencoder实施转码,但是转码过程中出现子进程阻塞,而且还是看了API才知道这个问题。因为mencoder 控制台输...
  • 信号的阻塞和未决信号,一个信号从产生到处理完毕完整过程进程通讯
  • 进程控制

    2021-04-04 11:19:39
    文章目录2.3进程控制1.操作系统的内核1....进程阻塞的过程3.进程的唤醒过程5.进程的挂起与激活1.进程的挂起2.进程的激活过程 2.3进程控制 1.操作系统的内核 现在的操作系统一般将OS划分为若干层次,将OS的
  • 进程切换过程

    2020-12-07 16:13:01
    PCB控制块是以链表方式存放,就绪进程的PCB放置在同一个链表之中,阻塞在同一个链表当中 当进程进行切换时候 1.保存当前的进程状态,包括程序计数器,寄存器保存在PCB中 2.更新PCB信息,例如更新进程的状态,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,755
精华内容 1,102
关键字:

进程阻塞的过程