Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2019-05-27:谈谈线程阻塞的原因? #63

Open
MoJieBlog opened this issue May 27, 2019 · 6 comments
Open

2019-05-27:谈谈线程阻塞的原因? #63

MoJieBlog opened this issue May 27, 2019 · 6 comments
Labels

Comments

@MoJieBlog
Copy link
Collaborator

No description provided.

@gabyallen
Copy link

1、线程执行了Thread.sleep(int n)方法,线程放弃CPU,睡眠n毫秒,然后恢复运行。

2、线程要执行一段同步代码,由于无法获得相关的同步锁,只好进入阻塞状态,等到获得了同步锁,才能恢复运行。

3、线程执行了一个对象的wait()方法,进入阻塞状态,只有等到其他线程执行了该对象的notify()或notifyAll()方法,才可能将其唤醒。

4、线程执行I/O操作或进行远程通信时,会因为等待相关的资源而进入阻塞状态。例如,当线程执行System.in.read()方法时,如果用户没有向控制台输入数据,则该线程会一直等读到了用户的输入数据才从read()方法返回。进行远程通信时,在客户程序中,线程在以下情况可能进入阻塞状态。

5、请求与服务器建立连接时,即当线程执行Socket的带参数的构造方法,或执行Socket的connect()方法时,会进入阻塞状态,直到连接成功,此线程才从Socket的构造方法或connect()方法返回。

6、线程从Socket的输入流读取数据时,如果没有足够的数据,就会进入阻塞状态,直到读到了足够的数据,或者到达输入流的末尾,或者出现了异常,才从输入流的read()方法返回或异常中断。输入流中有多少数据才算足够呢?这要看线程执行的read()方法的类型。

int read(); 只要输入流中有一个字节,就算足够。

int read(byte[] buff); 只要输入流中的字节数目与参数buff数组的长度相同,就算足够。

String readLine(); 只要输入流中邮一行字符串,就算足够。值得注意的是,InputStream类并没有readLine方法,在过滤流BufferedReader类中才有此方法。

7、线程向Socket的输出流写一批数据时,可能会进入阻塞状态,等到输出了所有的数据,或者出现异常,才从输出流的write()方法返回或异常中断。

8、调用Socket的setSoLinger()方法设置了关闭Socket的延迟时间,那么当线程执行Socket的close方法时,会进入阻塞状态,直到底层Socket发送完所有剩余数据,或者超过了setSoLinger()方法设置的延迟时间,才从close()方法返回。

@canyie
Copy link

canyie commented May 27, 2019

  • I/O
  • 同步操作(synchronized、wait()、LockSupport等)
  • Thread.sleep()/Thread.join()
  • 被其他线程挂起

暂时只能想到那么多。。

@yangfanggang
Copy link

阻塞状态可以分为三种:

等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态

同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)

其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态

@Petterpx
Copy link

sleep 休眠綫程
wait 綫程等待
yield 綫程礼让
join 线程自闭
io操作时 比如等待某个输入输出流
抢占锁的时候

@kriswang24
Copy link

1 线程阻塞:所谓线程阻塞就是正在运行的线程没有运行结束,暂时让出CPU资源,进入阻塞状态。
2 线程阻塞状态的原因:
线程自己调用Thread.sleep()进入阻塞状态,睡眠n毫秒后进入就绪状态,等待CPU分配资源。
调用suspend使线程进入阻塞状态,并且不会自动恢复、必须其对应的resume被调用,才能使线程进入可行状态。
调用当前Object调用wait释放占用的锁(在同步代码块中),使当前线程进入阻塞状态。它有两种形式,一种允许 指定以毫秒为单位的一段时间作为参数,另一种没有参数,前者当对应的 notify() 被调用或者超出指定时间时线程重新进入可执行状态,后者则必须对应的 notify() 被调用。
IO操作时
join 线程自闭
请求与服务器建立连接时...

@Moosphan Moosphan added the 线程 label Aug 2, 2019
@Jmengfei
Copy link

Jmengfei commented Mar 29, 2021

阻塞状态是指线程因为某种原因放弃了 cpu 使用权,也即让出了 cpu timeslice,暂时停止运行。
线程阻塞分为三种情况:

  • 等待阻塞: Object.wait(),使线程让出cpu执行权,且释放锁。JVM会把该线程放入等待队列中。
  • 同步阻塞:lock,running中的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则 JVM 会把该线
    程放入锁池(lock pool)中。
  • 其他阻塞:Sleep/join
    • 线程休眠:Thread.sleep (long millis)方法,使该线程让出cpu执行权,但不释放锁。线程转到阻塞状态。millis结束后直接进入就绪状态。
    • I/O请求: 当发生IO请求时,可能会在读写端都有可能发生IO阻塞。
    • suspend/resume (没用过)
      很多文章都说yield()也是阻塞的一种,其实是不准确的,yield() 可以使的当前线程放弃cpu分得的时间片,但没有经过阻塞状态。切记,这个差别很重要。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants