thread
ReaderWriterMutex
A ReaderWriterMutex is used to achieve mutual exclusion between threads, similar to a Mutex.
Unlike a Mutex, a ReaderWriterMutex can be used to gain exclusive (writer) or shared (reader)
access to what it guards. A flaw in relation to a Mutex is that it cannot be used with a condition variable.
A ReaderWriterMutex can be in one of three states:
// - Free - not owned by any thread,
// - Exclusive - owned by a single thread,
// - Shared(n) - shared amongst n threads.
DEBUG
trace(),assert()都只是在DEBUG的模式下才起作用的,如果定义了NDEBUG,编译器会认为是非DEBUG的模式(虽然编译出来的程序还是很大,而且还可以进行调试),此时trace(),assert()就没有用了.就如同你编译成release版的时候这些没有用一样.
Java中的多线程是一种抢占机制而不是分时机制。抢占机制指的是有多个线程处于可运行状态,但是只允许一个线程在运行,他们通过竞争的方式抢占CPU。
新生状态(New): 当一个线程的实例被创建即使用new关键字和Thread类或其子类创建一个线程对象后,此时该线程处于新生(new)状态,处于新生状态的线程有自己的内存空间,但该线程并没有运行,此时线程还不是活着的(not alive);
  就绪状态(Runnable): 通过调用线程实例的start()方法来启动线程使线程进入就绪状态(runnable);处于就绪状态的线程已经具备了运行条件,但还没有被分配到CPU即不一定会被立即执行,此时处于线程就绪队列,等待系统为其分配CPCU,等待状态并不是执行状态;此时线程是活着的(alive);
  运行状态(Running): 一旦获取CPU(被JVM选中),线程就进入运行(running)状态,线程的run()方法才开始被执行;在运行状态的线程执行自己的run()方法中的操作,直到调用其他的方法而终止、或者等待某种资源而阻塞、或者完成任务而死亡;如果在给定的时间片内没有执行结束,就会被系统给换下来回到线程的等待状态;此时线程是活着的(alive);
  阻塞状态(Blocked):通过调用join()、sleep()、wait()或者资源被暂用使线程处于阻塞(blocked)状态;处于Blocking状态的线程仍然是活着的(alive)
  死亡状态(Dead):当一个线程的run()方法运行完毕或被中断或被异常退出,该线程到达死亡(dead)状态。此时可能仍然存在一个该Thread的实例对象,当该Thready已经不可能在被作为一个可被独立执行的线程对待了,线程的独立的call stack已经被dissolved。一旦某一线程进入Dead状态,他就再也不能进入一个独立线程的生命周期了。对于一个处于Dead状态的线程调用start()方法,会出现一个运行期(runtime exception)的异常;处于Dead状态的线程不是活着的(not alive)。
1)优先级(priority)
  每个类都有自己的优先级,一般property用1-10的整数表示,默认优先级是5,优先级最高是10;优先级高的线程并不一定比优先级低的线程执行的机会高,只是执行的机率高;默认一个线程的优先级和创建他的线程优先级相同;
2)Thread.sleep()/sleep(long millis)
  当前线程睡眠/millis的时间(millis指定睡眠时间是其最小的不执行时间,因为sleep(millis)休眠到达后,无法保证会被JVM立即调度);sleep()是一个静态方法(static method) ,所以他不会停止其他的线程也处于休眠状态;线程sleep()时不会失去拥有的对象锁。作用:保持对象锁,让出CPU,调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留一定的时间给其他线程执行的机会;
3)Thread.yield()
  让出CPU的使用权,给其他线程执行机会、让同等优先权的线程运行(但并不保证当前线程会被JVM再次调度、使该线程重新进入Running状态),如果没有同等优先权的线程,那么yield()方法将不会起作用。
4)thread.join()
 使用该方法的线程会在此之间执行完毕后再往下继续执行。
5)object.wait()
  当一个线程执行到wait()方法时,他就进入到一个和该对象相关的等待池(Waiting Pool)中,同时失去了对象的机锁—暂时的,wait后还要返还对象锁。当前线程必须拥有当前对象的锁,如果当前线程不是此锁的拥有者,会抛出IllegalMonitorStateException异常,所以wait()必须在synchronized block中调用。
6)object.notify()/notifyAll()
  唤醒在当前对象等待池中等待的第一个线程/所有线程。notify()/notifyAll()也必须拥有相同对象锁,否则也会抛出IllegalMonitorStateException异常。
//libcore/libart/src/main/java/java/lang/Thread.java public class Thread implements Runnable { /** * A representation of a thread's state. A given thread may only be in one * state at a time. */ public enum State { /** * The thread has been created, but has never been started. */ NEW, /** * The thread may be run. */ RUNNABLE, /** * The thread is blocked and waiting for a lock. */ BLOCKED, /** * The thread is waiting. */ WAITING, /** * The thread is waiting for a specified amount of time. */ TIMED_WAITING, /** * The thread has been terminated. */ TERMINATED } /** * The maximum priority value allowed for a thread. * This corresponds to (but does not have the same value as) * {@code android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY}. */ public static final int MAX_PRIORITY = 10; /** * The minimum priority value allowed for a thread. * This corresponds to (but does not have the same value as) * {@code android.os.Process.THREAD_PRIORITY_LOWEST}. */ public static final int MIN_PRIORITY = 1; /** * The normal (default) priority value assigned to the main thread. * This corresponds to (but does not have the same value as) * {@code android.os.Process.THREAD_PRIORITY_DEFAULT}. */ public static final int NORM_PRIORITY = 5; /* Some of these are accessed directly by the VM; do not rename them. */ private volatile long nativePeer; volatile ThreadGroup group; volatile boolean daemon; volatile String name; //初始化时线程的名字 default: "Thread-" + id; volatile int priority; volatile long stackSize; Runnable target; //传进来的runnable private static int count = 0; //计数线程组里面有几个线程 /** * Holds the thread's ID. We simply count upwards, so * each Thread has a unique ID. */ private long id; /** * Normal thread local values. */ ThreadLocal.Values localValues; //group:每一个线程都属于一个group,当线程被创建时就会加入一个特定的group,当线程运行结束,会从这个 group 中移除; //daemon:当前线程是不是守护线程,守护线程只会在没有非守护线程运行的情况下才会运行; //priority:线程优先级,Java Thread 类的线程优先级取值范围为 [1, 10],默认优先级为 5; //stackSize:线程栈大小,默认为 0,即使用默认的线程栈大小(由 dalvik 中的全局变量 gDvm.stackSize 决定); //target:一个 Runnable 对象,Thread 的 run() 方法中会转掉该 target 的 run() 方法,这是线程真正处理事务的地方; //id:Android 线程 id,通过递增 count 得到该 id,如果没有显示给线程设置名字,那么就会使用 Thread+id 当作线程的名字。注意这不是真正意义上的线程 id,即在 logcat 中打印的 tid 并不是这个 id,那 tid 是指 dalvik 线程的 id; //localValues:线程本地存储(TLS)数据; /** * Reflects whether this Thread has already been started. A Thread * can only be started once (no recycling). Also, we need it to deduce * the proper Thread status. */ boolean hasBeenStarted = false; public Thread(String threadName) { if (threadName == null) { throw new NullPointerException("threadName == null"); } create(null, null, threadName, 0); } private void create(ThreadGroup group, Runnable runnable, String threadName, long stackSize) { Thread currentThread = Thread.currentThread(); if (group == null) { group = currentThread.getThreadGroup(); } if (group.isDestroyed()) { throw new IllegalThreadStateException("Group already destroyed"); } this.group = group; synchronized (Thread.class) { id = ++Thread.count; } if (threadName == null) { this.name = "Thread-" + id; } else { this.name = threadName; } this.target = runnable; this.stackSize = stackSize; this.priority = currentThread.getPriority(); this.contextClassLoader = currentThread.contextClassLoader; // Transfer over InheritableThreadLocals. if (currentThread.inheritableValues != null) { inheritableValues = new ThreadLocal.Values(currentThread.inheritableValues); } // add ourselves to our ThreadGroup of choice this.group.addThread(this); } public synchronized void start() { checkNotStarted(); hasBeenStarted = true; nativeCreate(this, stackSize, daemon); } public static native Thread currentThread(); private native static void nativeCreate(Thread t, long stackSize, boolean daemon); }
/art/runtime/native/java_lang_Thread.cc static void Thread_nativeCreate(JNIEnv* env, jclass, jobject java_thread, jlong stack_size, jboolean daemon) { Thread::CreateNativeThread(env, java_thread, stack_size, daemon == JNI_TRUE); }
// art/runtime/native/java_lang_Thread.cc void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_size, bool is_daemon) { CHECK(java_peer != nullptr);//即为java层的thread实例,包裹着run方法的具体实现 Thread* self = static_cast<JNIEnvExt*>(env)->self; Runtime* runtime = Runtime::Current(); // Atomically start the birth of the thread ensuring the runtime isn't shutting down. bool thread_start_during_shutdown = false;//这段代码用来检测thread是否在runtime宕机时start的 { MutexLock mu(self, *Locks::runtime_shutdown_lock_); if (runtime->IsShuttingDownLocked()) { thread_start_during_shutdown = true; } else { runtime->StartThreadBirth(); } } if (thread_start_during_shutdown) {//若runtime宕机了就抛出异常 ScopedLocalRef<jclass> error_class(env, env->FindClass("java/lang/InternalError")); env->ThrowNew(error_class.get(), "Thread starting during runtime shutdown"); return; } Thread* child_thread = new Thread(is_daemon);//新建子线程 // Use global JNI ref to hold peer live while child thread starts. child_thread->tlsPtr_.jpeer = env->NewGlobalRef(java_peer);//把java层的run方法实体传递给子线程 stack_size = FixStackSize(stack_size); // Thread.start is synchronized, so we know that nativePeer is 0, and know that we're not racing to // assign it. env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer, reinterpret_cast<jlong>(child_thread)); pthread_t new_pthread; pthread_attr_t attr; CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), "new thread"); CHECK_PTHREAD_CALL(pthread_attr_setdetachstate, (&attr, PTHREAD_CREATE_DETACHED), "PTHREAD_CREATE_DETACHED"); CHECK_PTHREAD_CALL(pthread_attr_setstacksize, (&attr, stack_size), stack_size); //创建新线程的方法,返回一个标志 int pthread_create_result = pthread_create(&new_pthread, &attr, Thread::CreateCallback, child_thread); CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), "new thread"); //线程创建如果失败则清除子线程信息,释放空间 if (pthread_create_result != 0) { // pthread_create(3) failed, so clean up. { MutexLock mu(self, *Locks::runtime_shutdown_lock_); runtime->EndThreadBirth(); } // Manually delete the global reference since Thread::Init will not have been run. env->DeleteGlobalRef(child_thread->tlsPtr_.jpeer); child_thread->tlsPtr_.jpeer = nullptr; delete child_thread; child_thread = nullptr; // TODO: remove from thread group? env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer, 0); { std::string msg(StringPrintf("pthread_create (%s stack) failed: %s", PrettySize(stack_size).c_str(), strerror(pthread_create_result))); ScopedObjectAccess soa(env); soa.Self()->ThrowOutOfMemoryError(msg.c_str()); } } }
//art/runtime/thread.cc void* Thread::CreateCallback(void* arg) { Thread* self = reinterpret_cast<Thread*>(arg); Runtime* runtime = Runtime::Current(); if (runtime == nullptr) { LOG(ERROR) << "Thread attaching to non-existent runtime: " << *self; return nullptr; } { // TODO: pass self to MutexLock - requires self to equal Thread::Current(), which is only true // after self->Init(). MutexLock mu(nullptr, *Locks::runtime_shutdown_lock_); // Check that if we got here we cannot be shutting down (as shutdown should never have started // while threads are being born). CHECK(!runtime->IsShuttingDownLocked()); self->Init(runtime->GetThreadList(), runtime->GetJavaVM()); Runtime::Current()->EndThreadBirth(); } { ScopedObjectAccess soa(self); // Copy peer into self, deleting global reference when done. CHECK(self->tlsPtr_.jpeer != nullptr); self->tlsPtr_.opeer = soa.Decode<mirror::Object*>(self->tlsPtr_.jpeer); self->GetJniEnv()->DeleteGlobalRef(self->tlsPtr_.jpeer); self->tlsPtr_.jpeer = nullptr; self->SetThreadName(self->GetThreadName(soa)->ToModifiedUtf8().c_str()); mirror::ArtField* priorityField = soa.DecodeField(WellKnownClasses::java_lang_Thread_priority); self->SetNativePriority(priorityField->GetInt(self->tlsPtr_.opeer)); Dbg::PostThreadStart(self); // Invoke the 'run' method of our java.lang.Thread. mirror::Object* receiver = self->tlsPtr_.opeer; jmethodID mid = WellKnownClasses::java_lang_Thread_run; InvokeVirtualOrInterfaceWithJValues(soa, receiver, mid, nullptr); } // Detach and delete self. Runtime::Current()->GetThreadList()->Unregister(self); return nullptr; }
//art/runtime/reflection.cc JValue InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, mirror::Object* receiver, jmethodID mid, jvalue* args) { // We want to make sure that the stack is not within a small distance from the // protected region in case we are calling into a leaf function whose stack // check has been elided. if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) { ThrowStackOverflowError(soa.Self()); return JValue(); } mirror::ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid)); uint32_t shorty_len = 0; const char* shorty = method->GetShorty(&shorty_len); JValue result; ArgArray arg_array(shorty, shorty_len); arg_array.BuildArgArrayFromJValues(soa, receiver, args); InvokeWithArgArray(soa, method, &arg_array, &result, shorty); return result; } static void InvokeWithArgArray(const ScopedObjectAccessAlreadyRunnable& soa, mirror::ArtMethod* method, ArgArray* arg_array, JValue* result, const char* shorty) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { uint32_t* args = arg_array->GetArray(); if (UNLIKELY(soa.Env()->check_jni)) { CheckMethodArguments(method, args); } method->Invoke(soa.Self(), args, arg_array->GetNumBytes(), result, shorty); }
 inline void Thread::CheckSuspend() {
+  LOG(ERROR) << "HTC+++++ Thread::CheckSuspend()";
+  android::CallStack stack(LOG_TAG);
   DCHECK_EQ(Thread::Current(), this);
01-01 00:17:09.430  5961  5961 E Chameleon: HTC+++ native current thread id: 5961
01-01 00:17:09.430  5961  5961 E art     : ThreadList::SuspendAll() ...
01-01 00:17:09.430  5961  5961 E art     :  MTK_ART_OPT_ENABLE is true.
01-01 00:17:09.430  5961  6070 E art     : HTC+++++ Thread::CheckSuspend()
01-01 00:17:09.445  5961  6070 D         : #00 pc 0000000000539750  /system/lib64/libart.so (artTestSuspendFromCode+92)
01-01 00:17:09.445  5961  6070 D         : #01 pc 000000000012617c  /system/lib64/libart.so (art_quick_test_suspend+76)
01-01
 00:17:09.445  5961  6070 D         : #02 pc 00000000000caab4  
/data/app/com.example.chameleon-1/oat/arm64/base.odex (offset 0x103000) 
(void com.example.chameleon.MainActivity$2.run()+408)
01-01 00:17:09.445  5961  6070 D         : #03 pc 000000000011c924  /system/lib64/libart.so (art_quick_invoke_stub+580)
01-01
 00:17:09.445  5961  6070 D         : #04 pc 000000000012c7fc  
/system/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned 
int*, unsigned int, art::JValue*, char const*)+176)
01-01 
00:17:09.445  5961  6070 D         : #05 pc 000000000042d48c  
/system/lib64/libart.so 
(art::InvokeVirtualOrInterfaceWithJValues(art::ScopedObjectAccessAlreadyRunnable
 const&, _jobject*, _jmethodID*, jvalue*)+440)
01-01 
00:17:09.445  5961  6070 D         : #06 pc 000000000045c6ac  
/system/lib64/libart.so (art::Thread::CreateCallback(void*)+756)
01-01 00:17:09.445  5961  6070 D         : #07 pc 000000000006a044  /system/lib64/libc.so (__pthread_start(void*)+52)
01-01 00:17:09.445  5961  6070 D         : #08 pc 000000000001c844  /system/lib64/libc.so (__start_thread+16)
                    
                
                
            
        
浙公网安备 33010602011771号