android 线程 唤醒锁,Thread类线程结束会唤醒使用其对象做锁而睡眠的线程

首先回顾一下我们的基础知识。

sleep:

线程睡眠,不会释放锁

wait:

线程等待。释放锁。

notity:

唤醒随机一个当前对象等待的线程,并不会释放锁

notityAll:

唤醒所有当前对象等待的线程,并不会释放锁

遇到问题:

代码如下:

package com.zhen.ten_chapter.question;

/**

* @author zhen

* @Date 2019/4/18 10:17

*/

public class ThreadDemo {

public static void main(String[] args) {

To10X tos = new To10X(1, 10);

tos.start();

int res = tos.getResult();

System.out.println(res);

}

static class To10X extends Thread {

private int point = 1;

private int end = 10;

private int result = 0;

public To10X(int start, int end) {

this.point = start;

this.end = end;

}

@Override

public synchronized void run() {

while (point != end + 1) {

result += point++;

System.out.println(Thread.currentThread().getName() + "::" + result);

}

this.notify();

}

public synchronized int getResult() {

while(result == 0) {

try {

System.out.println("锁定前");

this.wait();

System.out.println("锁定后");

} catch (Exception e) {

e.printStackTrace();

}

}

return result;

}

}

}

程序发现wait总是会被唤醒。

怀疑是不是总是先wait然后再被notity了,于是将notify注释掉了,但依然被唤醒。

什么原因?

我关注点放在了static关键字上了,依稀记得static 方法的锁锁对象是类,那么static类里面的成员方法的锁对象是不是也是类呢?

当然是我多想了,但是我依然将static 的内部类改为了一个普通内部类,然后用实例化对象去创建的对应对象与执行方法。可是结果依旧是一样。

我接下来怀疑是主线程的原因

因为其他线程都是从主线程上衍生出来的,线程不是很熟练,依稀记得一些所谓守护线程等概念。于是简单写了一个Demo类,主线程wait,然后开一个线程获取到锁执行到结束,然后发现能wait住主线程

那是什么原因呢?

接下来我觉得一定是有什么东西唤醒了主线程,notity被我注释掉了,notityAll没有编写。查看wait的api,发现它没有自动唤醒的说法,有一个参数是延迟等待的意思。它明确声明了只能靠notity和notifyAll唤醒。百度大法好。我狂百度,发现有人遇到和我一样的问题,参考链接:  https://blog.csdn.net/nmyangym/article/details/7850882#commentBox 。为此,我也去看了一下所谓的jdk的Thread类的join源码,如下:

public final synchronized void join(long millis)

throws InterruptedException {

long base = System.currentTimeMillis();

long now = 0;

if (millis < 0) {

throw new IllegalArgumentException("timeout value is negative");

}

if (millis == 0) {

while (isAlive()) {

wait(0);

}

} else {

while (isAlive()) {

long delay = millis - now;

if (delay <= 0) {

break;

}

wait(delay);

now = System.currentTimeMillis() - base;

}

}

}

它确实调用了wait,但是调用了wait能保证唤醒吗?我感觉方向没问题了,继续针对点去百度

参考链接:

https://segmentfault.com/q/1010000016744022?utm_source=tag-newest

原来,Thread对象在线程结束的时候,会自动调用一次notifyAll语法,线程结束会执行join方法,join的jdk写法我们看到过,大牛给出的依据是openJDK中的源码:

int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);

static void *java_start(Thread *thread) {

...

thread->run();

return 0;

}

void JavaThread::run() {

...

thread_main_inner();

}

void JavaThread::thread_main_inner() {

...

this->exit(false);

delete this;

}

void JavaThread::exit(bool destroy_vm, ExitType exit_type) {

...

// Notify waiters on thread object. This has to be done after exit() is called

// on the thread (if the thread is the last thread in a daemon ThreadGroup the

// group should have the destroyed bit set before waiters are notified).

ensure_join(this);

...

}

static void ensure_join(JavaThread* thread) {

// We do not need to grap the Threads_lock, since we are operating on ourself.

Handle threadObj(thread, thread->threadObj());

assert(threadObj.not_null(), "java thread object must exist");

ObjectLocker lock(threadObj, thread);

// Ignore pending exception (ThreadDeath), since we are exiting anyway

thread->clear_pending_exception();

// Thread is exiting. So set thread_status field in java.lang.Thread class to TERMINATED.

java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED);

// Clear the native thread instance - this makes isAlive return false and allows the join()

// to complete once we've done the notify_all below

java_lang_Thread::set_thread(threadObj(), NULL);

lock.notify_all(thread);

// Ignore pending exception (ThreadDeath), since we are exiting anyway

thread->clear_pending_exception();

}

结论:

尽量不要用线程对象做同步锁的钥匙,线程结束的时候它会自动调用this.notifyAll()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值