Thread类是Android为线程操作而做的一个封装。代码在Thread.cpp中,其中还封装了一些与线程同步相关的类。

Thread类

Thread类的构造函数中的有一个canCallJava
Thread.cpp

/system/core/libutils/Threads.cpp

线程创建流程

/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ // #define LOG_NDEBUG 0
#define LOG_TAG "libutils.threads" #include <assert.h>
#include <errno.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> #if !defined(_WIN32)
# include <pthread.h>
# include <sched.h>
# include <sys/resource.h>
#else
# include <windows.h>
# include <stdint.h>
# include <process.h>
# define HAVE_CREATETHREAD // Cygwin, vs. HAVE__BEGINTHREADEX for MinGW
#endif #if defined(__linux__)
#include <sys/prctl.h>
#endif #include <utils/threads.h>
#include <utils/Log.h> #include <cutils/sched_policy.h> #ifdef HAVE_ANDROID_OS
# define __android_unused
#else
# define __android_unused __attribute__((__unused__))
#endif /*
* ===========================================================================
* Thread wrappers
* ===========================================================================
*/ using namespace android; // ----------------------------------------------------------------------------
#if !defined(_WIN32)
// ---------------------------------------------------------------------------- /*
* Create and run a new thread.
*
* We create it "detached", so it cleans up after itself.
*/ typedef void* (*android_pthread_entry)(void*); struct thread_data_t {
thread_func_t entryFunction;
void* userData;
int priority;
char * threadName; // we use this trampoline when we need to set the priority with
// nice/setpriority, and name with prctl.
static int trampoline(const thread_data_t* t) {
thread_func_t f = t->entryFunction;
void* u = t->userData;
int prio = t->priority;
char * name = t->threadName;
delete t;
setpriority(PRIO_PROCESS, , prio);
if (prio >= ANDROID_PRIORITY_BACKGROUND) {
set_sched_policy(, SP_BACKGROUND);
} else {
set_sched_policy(, SP_FOREGROUND);
} if (name) {
androidSetThreadName(name);
free(name);
}
return f(u);
}
}; void androidSetThreadName(const char* name) {
#if defined(__linux__)
// Mac OS doesn't have this, and we build libutil for the host too
int hasAt = ;
int hasDot = ;
const char *s = name;
while (*s) {
if (*s == '.') hasDot = ;
else if (*s == '@') hasAt = ;
s++;
}
int len = s - name;
if (len < || hasAt || !hasDot) {
s = name;
} else {
s = name + len - ;
}
prctl(PR_SET_NAME, (unsigned long) s, , , );
#endif
} int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
void *userData,
const char* threadName __android_unused,
int32_t threadPriority,
size_t threadStackSize,
android_thread_id_t *threadId)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); #ifdef HAVE_ANDROID_OS /* valgrind is rejecting RT-priority create reqs */
if (threadPriority != PRIORITY_DEFAULT || threadName != NULL) {
// Now that the pthread_t has a method to find the associated
// android_thread_id_t (pid) from pthread_t, it would be possible to avoid
// this trampoline in some cases as the parent could set the properties
// for the child. However, there would be a race condition because the
// child becomes ready immediately, and it doesn't work for the name.
// prctl(PR_SET_NAME) only works for self; prctl(PR_SET_THREAD_NAME) was
// proposed but not yet accepted.
thread_data_t* t = new thread_data_t;
t->priority = threadPriority;
t->threadName = threadName ? strdup(threadName) : NULL;
t->entryFunction = entryFunction;
t->userData = userData;
entryFunction = (android_thread_func_t)&thread_data_t::trampoline;
userData = t;
}
#endif if (threadStackSize) {
pthread_attr_setstacksize(&attr, threadStackSize);
} errno = ;
pthread_t thread;
int result = pthread_create(&thread, &attr,
(android_pthread_entry)entryFunction, userData);
pthread_attr_destroy(&attr);
if (result != ) {
ALOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n"
"(android threadPriority=%d)",
entryFunction, result, errno, threadPriority);
return ;
} // Note that *threadID is directly available to the parent only, as it is
// assigned after the child starts. Use memory barrier / lock if the child
// or other threads also need access.
if (threadId != NULL) {
*threadId = (android_thread_id_t)thread; // XXX: this is not portable
}
return ;
} #ifdef HAVE_ANDROID_OS
static pthread_t android_thread_id_t_to_pthread(android_thread_id_t thread)
{
return (pthread_t) thread;
}
#endif android_thread_id_t androidGetThreadId()
{
return (android_thread_id_t)pthread_self();
} // ----------------------------------------------------------------------------
#else // !defined(_WIN32)
// ---------------------------------------------------------------------------- /*
* Trampoline to make us __stdcall-compliant.
*
* We're expected to delete "vDetails" when we're done.
*/
struct threadDetails {
int (*func)(void*);
void* arg;
};
static __stdcall unsigned int threadIntermediary(void* vDetails)
{
struct threadDetails* pDetails = (struct threadDetails*) vDetails;
int result; result = (*(pDetails->func))(pDetails->arg); delete pDetails; ALOG(LOG_VERBOSE, "thread", "thread exiting\n");
return (unsigned int) result;
} /*
* Create and run a new thread.
*/
static bool doCreateThread(android_thread_func_t fn, void* arg, android_thread_id_t *id)
{
HANDLE hThread;
struct threadDetails* pDetails = new threadDetails; // must be on heap
unsigned int thrdaddr; pDetails->func = fn;
pDetails->arg = arg; #if defined(HAVE__BEGINTHREADEX)
hThread = (HANDLE) _beginthreadex(NULL, , threadIntermediary, pDetails, ,
&thrdaddr);
if (hThread == )
#elif defined(HAVE_CREATETHREAD)
hThread = CreateThread(NULL, ,
(LPTHREAD_START_ROUTINE) threadIntermediary,
(void*) pDetails, , (DWORD*) &thrdaddr);
if (hThread == NULL)
#endif
{
ALOG(LOG_WARN, "thread", "WARNING: thread create failed\n");
return false;
} #if defined(HAVE_CREATETHREAD)
/* close the management handle */
CloseHandle(hThread);
#endif if (id != NULL) {
*id = (android_thread_id_t)thrdaddr;
} return true;
} int androidCreateRawThreadEtc(android_thread_func_t fn,
void *userData,
const char* /*threadName*/,
int32_t /*threadPriority*/,
size_t /*threadStackSize*/,
android_thread_id_t *threadId)
{
return doCreateThread( fn, userData, threadId);
} android_thread_id_t androidGetThreadId()
{
return (android_thread_id_t)GetCurrentThreadId();
} // ----------------------------------------------------------------------------
#endif // !defined(_WIN32) // ---------------------------------------------------------------------------- int androidCreateThread(android_thread_func_t fn, void* arg)
{
return createThreadEtc(fn, arg);
} int androidCreateThreadGetID(android_thread_func_t fn, void *arg, android_thread_id_t *id)
{
return createThreadEtc(fn, arg, "android:unnamed_thread",
PRIORITY_DEFAULT, , id);
} static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc; int androidCreateThreadEtc(android_thread_func_t entryFunction,
void *userData,
const char* threadName,
int32_t threadPriority,
size_t threadStackSize,
android_thread_id_t *threadId)
{
return gCreateThreadFn(entryFunction, userData, threadName,
threadPriority, threadStackSize, threadId);
} void androidSetCreateThreadFunc(android_create_thread_fn func)
{
gCreateThreadFn = func;
} #ifdef HAVE_ANDROID_OS
int androidSetThreadPriority(pid_t tid, int pri)
{
int rc = ; #if !defined(_WIN32)
int lasterr = ; if (pri >= ANDROID_PRIORITY_BACKGROUND) {
rc = set_sched_policy(tid, SP_BACKGROUND);
} else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND) {
rc = set_sched_policy(tid, SP_FOREGROUND);
} if (rc) {
lasterr = errno;
} if (setpriority(PRIO_PROCESS, tid, pri) < ) {
rc = INVALID_OPERATION;
} else {
errno = lasterr;
}
#endif return rc;
} int androidGetThreadPriority(pid_t tid) {
#if !defined(_WIN32)
return getpriority(PRIO_PROCESS, tid);
#else
return ANDROID_PRIORITY_NORMAL;
#endif
} #endif namespace android { /*
* ===========================================================================
* Mutex class
* ===========================================================================
*/ #if !defined(_WIN32)
// implemented as inlines in threads.h
#else Mutex::Mutex()
{
HANDLE hMutex; assert(sizeof(hMutex) == sizeof(mState)); hMutex = CreateMutex(NULL, FALSE, NULL);
mState = (void*) hMutex;
} Mutex::Mutex(const char* name)
{
// XXX: name not used for now
HANDLE hMutex; assert(sizeof(hMutex) == sizeof(mState)); hMutex = CreateMutex(NULL, FALSE, NULL);
mState = (void*) hMutex;
} Mutex::Mutex(int type, const char* name)
{
// XXX: type and name not used for now
HANDLE hMutex; assert(sizeof(hMutex) == sizeof(mState)); hMutex = CreateMutex(NULL, FALSE, NULL);
mState = (void*) hMutex;
} Mutex::~Mutex()
{
CloseHandle((HANDLE) mState);
} status_t Mutex::lock()
{
DWORD dwWaitResult;
dwWaitResult = WaitForSingleObject((HANDLE) mState, INFINITE);
return dwWaitResult != WAIT_OBJECT_0 ? - : NO_ERROR;
} void Mutex::unlock()
{
if (!ReleaseMutex((HANDLE) mState))
ALOG(LOG_WARN, "thread", "WARNING: bad result from unlocking mutex\n");
} status_t Mutex::tryLock()
{
DWORD dwWaitResult; dwWaitResult = WaitForSingleObject((HANDLE) mState, );
if (dwWaitResult != WAIT_OBJECT_0 && dwWaitResult != WAIT_TIMEOUT)
ALOG(LOG_WARN, "thread", "WARNING: bad result from try-locking mutex\n");
return (dwWaitResult == WAIT_OBJECT_0) ? : -;
} #endif // !defined(_WIN32) /*
* ===========================================================================
* Condition class
* ===========================================================================
*/ #if !defined(_WIN32)
// implemented as inlines in threads.h
#else /*
* Windows doesn't have a condition variable solution. It's possible
* to create one, but it's easy to get it wrong. For a discussion, and
* the origin of this implementation, see:
*
* http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
*
* The implementation shown on the page does NOT follow POSIX semantics.
* As an optimization they require acquiring the external mutex before
* calling signal() and broadcast(), whereas POSIX only requires grabbing
* it before calling wait(). The implementation here has been un-optimized
* to have the correct behavior.
*/
typedef struct WinCondition {
// Number of waiting threads.
int waitersCount; // Serialize access to waitersCount.
CRITICAL_SECTION waitersCountLock; // Semaphore used to queue up threads waiting for the condition to
// become signaled.
HANDLE sema; // An auto-reset event used by the broadcast/signal thread to wait
// for all the waiting thread(s) to wake up and be released from
// the semaphore.
HANDLE waitersDone; // This mutex wouldn't be necessary if we required that the caller
// lock the external mutex before calling signal() and broadcast().
// I'm trying to mimic pthread semantics though.
HANDLE internalMutex; // Keeps track of whether we were broadcasting or signaling. This
// allows us to optimize the code if we're just signaling.
bool wasBroadcast; status_t wait(WinCondition* condState, HANDLE hMutex, nsecs_t* abstime)
{
// Increment the wait count, avoiding race conditions.
EnterCriticalSection(&condState->waitersCountLock);
condState->waitersCount++;
//printf("+++ wait: incr waitersCount to %d (tid=%ld)\n",
// condState->waitersCount, getThreadId());
LeaveCriticalSection(&condState->waitersCountLock); DWORD timeout = INFINITE;
if (abstime) {
nsecs_t reltime = *abstime - systemTime();
if (reltime < )
reltime = ;
timeout = reltime/;
} // Atomically release the external mutex and wait on the semaphore.
DWORD res =
SignalObjectAndWait(hMutex, condState->sema, timeout, FALSE); //printf("+++ wait: awake (tid=%ld)\n", getThreadId()); // Reacquire lock to avoid race conditions.
EnterCriticalSection(&condState->waitersCountLock); // No longer waiting.
condState->waitersCount--; // Check to see if we're the last waiter after a broadcast.
bool lastWaiter = (condState->wasBroadcast && condState->waitersCount == ); //printf("+++ wait: lastWaiter=%d (wasBc=%d wc=%d)\n",
// lastWaiter, condState->wasBroadcast, condState->waitersCount); LeaveCriticalSection(&condState->waitersCountLock); // If we're the last waiter thread during this particular broadcast
// then signal broadcast() that we're all awake. It'll drop the
// internal mutex.
if (lastWaiter) {
// Atomically signal the "waitersDone" event and wait until we
// can acquire the internal mutex. We want to do this in one step
// because it ensures that everybody is in the mutex FIFO before
// any thread has a chance to run. Without it, another thread
// could wake up, do work, and hop back in ahead of us.
SignalObjectAndWait(condState->waitersDone, condState->internalMutex,
INFINITE, FALSE);
} else {
// Grab the internal mutex.
WaitForSingleObject(condState->internalMutex, INFINITE);
} // Release the internal and grab the external.
ReleaseMutex(condState->internalMutex);
WaitForSingleObject(hMutex, INFINITE); return res == WAIT_OBJECT_0 ? NO_ERROR : -;
}
} WinCondition; /*
* Constructor. Set up the WinCondition stuff.
*/
Condition::Condition()
{
WinCondition* condState = new WinCondition; condState->waitersCount = ;
condState->wasBroadcast = false;
// semaphore: no security, initial value of 0
condState->sema = CreateSemaphore(NULL, , 0x7fffffff, NULL);
InitializeCriticalSection(&condState->waitersCountLock);
// auto-reset event, not signaled initially
condState->waitersDone = CreateEvent(NULL, FALSE, FALSE, NULL);
// used so we don't have to lock external mutex on signal/broadcast
condState->internalMutex = CreateMutex(NULL, FALSE, NULL); mState = condState;
} /*
* Destructor. Free Windows resources as well as our allocated storage.
*/
Condition::~Condition()
{
WinCondition* condState = (WinCondition*) mState;
if (condState != NULL) {
CloseHandle(condState->sema);
CloseHandle(condState->waitersDone);
delete condState;
}
} status_t Condition::wait(Mutex& mutex)
{
WinCondition* condState = (WinCondition*) mState;
HANDLE hMutex = (HANDLE) mutex.mState; return ((WinCondition*)mState)->wait(condState, hMutex, NULL);
} status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
{
WinCondition* condState = (WinCondition*) mState;
HANDLE hMutex = (HANDLE) mutex.mState;
nsecs_t absTime = systemTime()+reltime; return ((WinCondition*)mState)->wait(condState, hMutex, &absTime);
} /*
* Signal the condition variable, allowing one thread to continue.
*/
void Condition::signal()
{
WinCondition* condState = (WinCondition*) mState; // Lock the internal mutex. This ensures that we don't clash with
// broadcast().
WaitForSingleObject(condState->internalMutex, INFINITE); EnterCriticalSection(&condState->waitersCountLock);
bool haveWaiters = (condState->waitersCount > );
LeaveCriticalSection(&condState->waitersCountLock); // If no waiters, then this is a no-op. Otherwise, knock the semaphore
// down a notch.
if (haveWaiters)
ReleaseSemaphore(condState->sema, , ); // Release internal mutex.
ReleaseMutex(condState->internalMutex);
} /*
* Signal the condition variable, allowing all threads to continue.
*
* First we have to wake up all threads waiting on the semaphore, then
* we wait until all of the threads have actually been woken before
* releasing the internal mutex. This ensures that all threads are woken.
*/
void Condition::broadcast()
{
WinCondition* condState = (WinCondition*) mState; // Lock the internal mutex. This keeps the guys we're waking up
// from getting too far.
WaitForSingleObject(condState->internalMutex, INFINITE); EnterCriticalSection(&condState->waitersCountLock);
bool haveWaiters = false; if (condState->waitersCount > ) {
haveWaiters = true;
condState->wasBroadcast = true;
} if (haveWaiters) {
// Wake up all the waiters.
ReleaseSemaphore(condState->sema, condState->waitersCount, ); LeaveCriticalSection(&condState->waitersCountLock); // Wait for all awakened threads to acquire the counting semaphore.
// The last guy who was waiting sets this.
WaitForSingleObject(condState->waitersDone, INFINITE); // Reset wasBroadcast. (No crit section needed because nobody
// else can wake up to poke at it.)
condState->wasBroadcast = ;
} else {
// nothing to do
LeaveCriticalSection(&condState->waitersCountLock);
} // Release internal mutex.
ReleaseMutex(condState->internalMutex);
} #endif // !defined(_WIN32) // ---------------------------------------------------------------------------- /*
* This is our thread object!
*/ Thread::Thread(bool canCallJava)
: mCanCallJava(canCallJava),
mThread(thread_id_t(-)),
mLock("Thread::mLock"),
mStatus(NO_ERROR),
mExitPending(false), mRunning(false)
#ifdef HAVE_ANDROID_OS
, mTid(-)
#endif
{
} Thread::~Thread()
{
} status_t Thread::readyToRun()
{
return NO_ERROR;
} status_t Thread::run(const char* name, int32_t priority, size_t stack)
{
Mutex::Autolock _l(mLock); if (mRunning) {
// thread already started
return INVALID_OPERATION;
} // reset status and exitPending to their default value, so we can
// try again after an error happened (either below, or in readyToRun())
mStatus = NO_ERROR;
mExitPending = false;
mThread = thread_id_t(-); // hold a strong reference on ourself
mHoldSelf = this; mRunning = true; bool res;
if (mCanCallJava) {
res = createThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
} else {
res = androidCreateRawThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
} if (res == false) {
mStatus = UNKNOWN_ERROR; // something happened!
mRunning = false;
mThread = thread_id_t(-);
mHoldSelf.clear(); // "this" may have gone away after this. return UNKNOWN_ERROR;
} // Do not refer to mStatus here: The thread is already running (may, in fact
// already have exited with a valid mStatus result). The NO_ERROR indication
// here merely indicates successfully starting the thread and does not
// imply successful termination/execution.
return NO_ERROR; // Exiting scope of mLock is a memory barrier and allows new thread to run
} int Thread::_threadLoop(void* user)
{
Thread* const self = static_cast<Thread*>(user); sp<Thread> strong(self->mHoldSelf);
wp<Thread> weak(strong);
self->mHoldSelf.clear(); #ifdef HAVE_ANDROID_OS
// this is very useful for debugging with gdb
self->mTid = gettid();
#endif bool first = true; do {
bool result;
if (first) {
first = false;
self->mStatus = self->readyToRun();
result = (self->mStatus == NO_ERROR); if (result && !self->exitPending()) {
// Binder threads (and maybe others) rely on threadLoop
// running at least once after a successful ::readyToRun()
// (unless, of course, the thread has already been asked to exit
// at that point).
// This is because threads are essentially used like this:
// (new ThreadSubclass())->run();
// The caller therefore does not retain a strong reference to
// the thread and the thread would simply disappear after the
// successful ::readyToRun() call instead of entering the
// threadLoop at least once.
result = self->threadLoop();
}
} else {
result = self->threadLoop();
} // establish a scope for mLock
{
Mutex::Autolock _l(self->mLock);
if (result == false || self->mExitPending) {
self->mExitPending = true;
self->mRunning = false;
// clear thread ID so that requestExitAndWait() does not exit if
// called by a new thread using the same thread ID as this one.
self->mThread = thread_id_t(-);
// note that interested observers blocked in requestExitAndWait are
// awoken by broadcast, but blocked on mLock until break exits scope
self->mThreadExitedCondition.broadcast();
break;
}
} // Release our strong reference, to let a chance to the thread
// to die a peaceful death.
strong.clear();
// And immediately, re-acquire a strong reference for the next loop
strong = weak.promote();
} while(strong != ); return ;
} void Thread::requestExit()
{
Mutex::Autolock _l(mLock);
mExitPending = true;
} status_t Thread::requestExitAndWait()
{
Mutex::Autolock _l(mLock);
if (mThread == getThreadId()) {
ALOGW(
"Thread (this=%p): don't call waitForExit() from this "
"Thread object's thread. It's a guaranteed deadlock!",
this); return WOULD_BLOCK;
} mExitPending = true; while (mRunning == true) {
mThreadExitedCondition.wait(mLock);
}
// This next line is probably not needed any more, but is being left for
// historical reference. Note that each interested party will clear flag.
mExitPending = false; return mStatus;
} status_t Thread::join()
{
Mutex::Autolock _l(mLock);
if (mThread == getThreadId()) {
ALOGW(
"Thread (this=%p): don't call join() from this "
"Thread object's thread. It's a guaranteed deadlock!",
this); return WOULD_BLOCK;
} while (mRunning == true) {
mThreadExitedCondition.wait(mLock);
} return mStatus;
} bool Thread::isRunning() const {
Mutex::Autolock _l(mLock);
return mRunning;
} #ifdef HAVE_ANDROID_OS
pid_t Thread::getTid() const
{
// mTid is not defined until the child initializes it, and the caller may need it earlier
Mutex::Autolock _l(mLock);
pid_t tid;
if (mRunning) {
pthread_t pthread = android_thread_id_t_to_pthread(mThread);
tid = pthread_gettid_np(pthread);
} else {
ALOGW("Thread (this=%p): getTid() is undefined before run()", this);
tid = -;
}
return tid;
}
#endif bool Thread::exitPending() const
{
Mutex::Autolock _l(mLock);
return mExitPending;
} }; // namespace android

http://androidxref.com/6.0.0_r1/xref/system/core/libutils/Threads.cpp

status_t Thread::run(const char* name, int32_tpriority, size_t stack)
{
Mutex::Autolock_l(mLock);
....
//如果mCanCallJava为真,则调用createThreadEtc函数,线程函数是_threadLoop。
//_threadLoop是Thread.cpp中定义的一个函数。
if(mCanCallJava) {
res = createThreadEtc(_threadLoop,this, name, priority,
stack,&mThread);
} else{
res = androidCreateRawThreadEtc(_threadLoop, this, name, priority,
stack,&mThread);
}

上面的mCanCallJava将线程创建函数的逻辑分为两个分支,虽传入的参数都有_threadLoop,但调用的函数却不同。先直接看mCanCallJava为true的这个分支 
Thread.h::createThreadEtc()

inline bool createThreadEtc(thread_func_tentryFunction,
void *userData,
const char*threadName = "android:unnamed_thread",
int32_tthreadPriority = PRIORITY_DEFAULT,
size_tthreadStackSize = 0,
thread_id_t*threadId = 0)
{
return androidCreateThreadEtc(entryFunction, userData, threadName,
threadPriority, threadStackSize,threadId) ? true : false;
}

它调用的是androidCreateThreadEtc函数

// gCreateThreadFn是函数指针,初始化时和mCanCallJava为false时使用的是同一个
//线程创建函数。
static android_create_thread_fn gCreateThreadFn= androidCreateRawThreadEtc;
int androidCreateThreadEtc(android_thread_func_tentryFunction,
void*userData,const char* threadName,
int32_tthreadPriority,size_t threadStackSize,
android_thread_id_t*threadId)
{
return gCreateThreadFn(entryFunction, userData, threadName,
threadPriority,threadStackSize, threadId);
}

androidCreateThreadEtc方法最终会调用CreateThreadFn方法,初始化时和mCanCallJava为false时使用的是同一个
线程创建函数,所以我们要看一下到底什么地方会修改这个mCanCallJava的值。答案就在AndroidRuntime调用startReg的地方,就有可能修改这个函数指针
AndroidRuntime.cpp

/*static*/ int AndroidRuntime::startReg(JNIEnv*env)
{
//这里会修改函数指针为javaCreateThreadEtc
androidSetCreateThreadFunc((android_create_thread_fn)javaCreateThreadEtc);
return ;
}

所以,如果mCanCallJava为true,则将调用javaCreateThreadEtc。 
AndroidRuntime.cpp

int AndroidRuntime::javaCreateThreadEtc(
android_thread_func_tentryFunction,
void* userData,
const char*threadName,
int32_tthreadPriority,
size_t threadStackSize,
android_thread_id_t* threadId)
{
void**args = (void**) malloc( * sizeof(void*));
intresult;
args[] = (void*) entryFunction;
args[] = userData;
args[] = (void*) strdup(threadName);
//调用的还是androidCreateRawThreadEtc,但线程函数却换成了javaThreadShell。
result= androidCreateRawThreadEtc(AndroidRuntime::javaThreadShell, args,
threadName, threadPriority,threadStackSize, threadId);
return result;
}

AndroidRuntime.cpp

http://androidxref.com/6.0.0_r1/xref/frameworks/base/core/jni/AndroidRuntime.cpp

int AndroidRuntime::javaThreadShell(void* args){
......
intresult;
//把这个线程attach到JNI环境中,这样这个线程就可以调用JNI的函数了
if(javaAttachThread(name, &env) != JNI_OK)
return -;
//调用实际的线程函数干活
result = (*(android_thread_func_t)start)(userData);
//从JNI环境中detach出来。
javaDetachThread();
free(name);
returnresult;
}

到这里,终于明白了mCanCallJava为true的目的:
1.在调用你的线程函数之前会attach到 JNI环境中,这样,你的线程函数就可以无忧无虑地使用JNI函数了。
2.线程函数退出后,它会从JNI环境中detach,释放一些资源。
进程退出前,dalvik虚拟机会检查是否有attach了,但是最后未detach的线程如果有,则会直接abort,这显然是不好的。

_threadLoop

还记得上面的代码

  if(mCanCallJava) {
res = createThreadEtc(_threadLoop,this, name, priority,
stack,&mThread);
} else{
res = androidCreateRawThreadEtc(_threadLoop, this, name, priority,
stack,&mThread);
}

尽管根据mCanCallJava不同会调用不同的函数,但是都是传入了_threadLoop,所以我们有必要分析这个方法。

int Thread::_threadLoop(void* user)
{
Thread* const self = static_cast<Thread*>(user);
sp<Thread> strong(self->mHoldSelf);
wp<Thread> weak(strong);
self->mHoldSelf.clear(); #if HAVE_ANDROID_OS
self->mTid = gettid();
#endif boolfirst = true; do {
bool result;
if(first) {
first = false;
//self代表继承Thread类的对象,第一次进来将调用readyToRun,看看是否准备好
self->mStatus = self->readyToRun();
result = (self->mStatus == NO_ERROR); if (result && !self->mExitPending) {
result = self->threadLoop();
}
}else {
/*
调用子类实现的threadLoop函数,注意这段代码运行在一个do-while循环中。
这表示即使我们的threadLoop返回了,线程也不一定会退出。
*/
result = self->threadLoop();
}
/*
线程退出的条件:
1)result 为false。这表明,如果子类在threadLoop中返回false,线程就可以
退出。这属于主动退出的情况,是threadLoop自己不想继续干活了,所以返回false。千万别写错threadLoop的返回值。
2)mExitPending为true,这个变量可由Thread类的requestExit函数设置,这种
情况属于被动退出,因为由外界强制设置了退出条件。
*/
if(result == false || self->mExitPending) {
self->mExitPending = true;
self->mLock.lock();
self->mRunning = false;
self->mThreadExitedCondition.broadcast();
self->mLock.unlock();
break;
}
strong.clear();
strong = weak.promote();
}while(strong != ); return ;
}

_threadLoop运行在一个循环中,它的返回值可以决定是否退出线程。

常用同步类

互斥类——Mutex
Mutex是互斥类,用于多线程访问同一个资源的时候,保证一次只能有一个线程能访问该资源。例如想象你在飞机上如厕,这时卫生间的信息牌上显示“有人”,你必须等里边的人出来后才可进去。这就是互斥的含义。

Thread.h::Mutex的声明和实现

inline Mutex::Mutex(int type, const char* name){
if(type == SHARED) {
//type如果是SHARED,则表明这个Mutex支持跨进程的线程同步
//在Audio系统和Surface系统中会经常见到这种用法
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&mMutex, &attr);
pthread_mutexattr_destroy(&attr);
} else {
pthread_mutex_init(&mMutex, NULL);
}
}
inline Mutex::~Mutex() {
pthread_mutex_destroy(&mMutex);
}
inline status_t Mutex::lock() {
return-pthread_mutex_lock(&mMutex);
}
inline void Mutex::unlock() {
pthread_mutex_unlock(&mMutex);
}
inline status_t Mutex::tryLock() {
return-pthread_mutex_trylock(&mMutex);
}

关于Mutex的使用,除了初始化外,最重要的是lock和unlock函数的使用,它们的用法如下:
要想独占卫生间,必须先调用Mutex的lock函数。这样,这个区域就被锁住了。如果这块区域之前已被别人锁住,lock函数则会等待,直到可以进入这块区域为止。系统保证一次只有一个线程能lock成功。
· 当你“方便”完毕,记得调用Mutex的unlock以释放互斥区域。这样,其他人的lock才可以成功返回。
· 另外,Mutex还提供了一个trylock函数,该函数只是尝试去锁住该区域,使用者需要根据trylock的返回值判断是否成功锁住了该区域。

AutoLock介绍
AutoLock类是定义在Mutex内部的一个类,Mutex的使用如下
· 显示调用Mutex的lock。
· 在某个时候要记住调用该Mutex的unlock。以上这些操作都必须一一对应,否则会出现“死锁”!充分利用了C++的构造和析构函数,可以达到不忘了释放锁的目的。
Thread.h Mutex::Autolock声明和实现

  classAutolock {
public:
//构造的时候调用lock
inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); }
inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
//析构的时候调用unlock
inline ~Autolock() { mLock.unlock(); }
private:
Mutex& mLock;
};

AutoLock的用法很简单:
· 先定义一个Mutex,如 Mutex xlock;
· 在使用xlock的地方,定义一个AutoLock,如 AutoLock autoLock(xlock)。
由于C++对象的构造和析构函数都是自动被调用的,所以在AutoLock的生命周期内,xlock的lock和unlock也就自动被调用了,这样就省去了重复书写unlock的麻烦,而且lock和unlock的调用肯定是一一对应的,这样就绝对不会出错。

条件类——Condition
· 线程A做初始化工作,而其他线程比如线程B、C必须等到初始化工作完后才能工作,即线程B、C在等待一个条件,我们称B、C为等待者。
· 当线程A完成初始化工作时,会触发这个条件,那么等待者B、C就会被唤醒。触发这个条件的A就是触发者。
Thread.h::Condition的声明和实现

class Condition {
public:
enum {
PRIVATE = ,
SHARED =
}; Condition();
Condition(int type);//如果type是SHARED,表示支持跨进程的条件同步
~Condition();
//线程B和C等待事件,wait这个名字是不是很形象呢?
status_t wait(Mutex& mutex);
//线程B和C的超时等待,B和C可以指定等待时间,当超过这个时间,条件却还不满足,则退出等待
status_t waitRelative(Mutex& mutex, nsecs_t reltime);
//触发者A用来通知条件已经满足,但是B和C只有一个会被唤醒
voidsignal();
//触发者A用来通知条件已经满足,所有等待者都会被唤醒
voidbroadcast(); private:
#if defined(HAVE_PTHREADS)
pthread_cond_t mCond;
#else
void* mState;
#endif
}

声明很简单,定义也很简单

inline Condition::Condition() {
pthread_cond_init(&mCond, NULL);
}
inline Condition::Condition(int type) {
if(type == SHARED) {//设置跨进程的同步支持
pthread_condattr_t attr;
pthread_condattr_init(&attr);
pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_cond_init(&mCond, &attr);
pthread_condattr_destroy(&attr);
} else{
pthread_cond_init(&mCond, NULL);
}
}
inline Condition::~Condition() {
pthread_cond_destroy(&mCond);
}
inline status_t Condition::wait(Mutex&mutex) {
return-pthread_cond_wait(&mCond, &mutex.mMutex);
}
inline status_tCondition::waitRelative(Mutex& mutex, nsecs_t reltime) {
#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
structtimespec ts;
ts.tv_sec = reltime/;
ts.tv_nsec = reltime%;
return-pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
...... //有些系统没有实现POSIX的相关函数,所以不同系统需要调用不同的函数
#endif
}
inline void Condition::signal() {
pthread_cond_signal(&mCond);
}
inline void Condition::broadcast() {
pthread_cond_broadcast(&mCond);
}

可以看出,Condition的实现全是凭借调用了Raw API的pthread_cond_xxx函数。这里要重点说明的是,Condition类必须配合Mutex来使用。上面代码中,不论是wait、waitRelative、signal还是broadcast的调用,都放在一个Mutex的lock和unlock范围中,尤其是wait和waitRelative函数的调用,这是强制性的。

Condition类和Mutex类使用的例子,在Thread类的requestExitAndWait中就可以体现
Thread.cpp

status_t Thread::requestExitAndWait()
{
......
requestExit();//设置退出变量mExitPending为true
Mutex::Autolock_l(mLock);//使用Autolock,mLock被锁住
while(mRunning == true) {
/*
条件变量的等待,这里为什么要通过while循环来反复检测mRunning?
因为某些时候即使条件类没有被触发,wait也会返回。
*/
mThreadExitedCondition.wait(mLock);
} mExitPending = false;
//退出前,局部变量Mutex::Autolock _l的析构会被调用,unlock也就会被自动调用。
returnmStatus;
}

Thread.cpp

int Thread::_threadLoop(void* user)
{
Thread* const self =static_cast<Thread*>(user);
sp<Thread> strong(self->mHoldSelf);
wp<Thread> weak(strong);
self->mHoldSelf.clear(); do {
......
result= self->threadLoop();//调用子类的threadLoop函数
......
//如果mExitPending为true,则退出
if(result == false || self->mExitPending) {
self->mExitPending = true;
//退出前触发条件变量,唤醒等待者
self->mLock.lock();//lock锁住
//mRunning的修改位于锁的保护中。
self->mRunning = false;
self->mThreadExitedCondition.broadcast();
self->mLock.unlock();//释放锁
break;//退出循环,此后该线程函数会退出
}
......
}while(strong != ); return0;
}

原子操作函数 
所谓原子操作,就是该操作绝不会在执行完毕前被任何其他任务或事件打断,也就说,原子操作是最小的执行单位

static int g_flag = ; //全局变量g_flag
static Mutex lock ;//全局的锁
//线程1执行thread1
void thread1()
{
//g_flag递减,每次操作前锁住
lock.lock();
g_flag--;
lock.unlock();
}
//线程2中执行thread2函数
void thread2()
{
lock.lock();
g_flag++; //线程2对g_flag进行递增操作,每次操作前要取得锁
lock.unlock();
}

为什么需要Mutex来帮忙呢?因为g_flags++或者g_flags—操作都不是原子操作。从汇编指令的角度看,C/C++中的一条语句对应了数条汇编指令。以g_flags++操作为例,它生成的汇编指令可能就是以下三条:
· 从内存中取数据到寄存器。
· 对寄存器中的数据进行递增操作,结果还在寄存器中。
· 寄存器的结果写回内存。
这三条汇编指令,如果按正常的顺序连续执行,是没有问题的,但在多线程时就不能保证了。例如,线程1在执行第一条指令后,线程2由于调度的原因,抢先在线程1之前连续执行完了三条指令。这样,线程1继续执行指令时,它所使用的值就不是线程2更新后的值,而是之前的旧值。再对这个值进行操作便没有意义了。
在一般情况下,处理这种问题可以使用Mutex来加锁保护,但Mutex的使用比它所要保护的内容还复杂,例如,锁的使用将导致从用户态转入内核态,有较大的浪费。那么,有没有简便些的办法让这些加、减等操作不被中断呢?
Android提供了相关的原子操作函数。这里,有必要介绍一下各个函数的作用。
Atomic.h
注意该文件位置在system/core/include/cutils目录中

//原子赋值操作,结果是*addr=value
void android_atomic_write(int32_t value,volatile int32_t* addr);
//下面所有函数的返回值都是操作前的旧值
//原子加1和原子减1
int32_t android_atomic_inc(volatile int32_t*addr);
int32_t android_atomic_dec(volatile int32_t*addr);
//原子加法操作,value为被加数
int32_t android_atomic_add(int32_t value,volatile int32_t* addr);
//原子“与”和“或”操作
int32_t android_atomic_and(int32_t value,volatile int32_t* addr);
int32_t android_atomic_or(int32_t value,volatile int32_t* addr);
/*
条件交换的原子操作。只有在oldValue等于*addr时,才会把newValue赋值给*addr
这个函数的返回值须特别注意。返回值非零,表示没有进行赋值操作。返回值为零,表示
进行了原子操作。
*/
int android_atomic_cmpxchg(int32_t oldvalue,int32_t newvalue,
volatile int32_t*addr);

Android Framework中Thread类的更多相关文章

  1. Android Framework中的线程Thread及它的threadLoop方法

    当初跟踪Camera的代码中的时候一直追到了HAL层,而在Framework中的代码看见了许很多多的Thread.它们普遍的特点就是有一个threadLoop方法.依照字面的意思应该是这个线程能够循环 ...

  2. [置顶] Android开发之Thread类分析

    在我们Linux系统中创建线程函数为:pthread_create(),在Android中我们为线程封装了一个类Thread,实际调用的还是pthread_create() 当我们想创建线程的时候,只 ...

  3. Android开发之Thread类分析 (转载)

    转自:http://blog.csdn.net/llping2011/article/details/9706599 在我们Linux系统中创建线程函数为:pthread_create(),在Andr ...

  4. Java中Thread类的start()和run()的区别

    1.start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码. 通 过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪 ...

  5. java中Thread类分析

    创建线程的方式有三种,一是创建Thread实例,二是实现Runnable接口,三是实现Callable接口,Runnable接口和Callable接口的区别是一个无返回值,一个有返回值:不管是Runn ...

  6. [Android Studio] Android Studio中查看类的继承关系

    转载自:http://blog.csdn.net/hyr83960944/article/details/38098091 查看类的继承关系的快捷键F4,在Android Studio常用快捷键这篇文 ...

  7. Android Studio中查看类的继承关系

    查看类的继承关系的快捷键F4.在Android Studio经常使用快捷键这篇文章中.有写了.今天主要是讲一些关于这个快捷键出来的界面的一些配置.这块功能相对偏冷一些,可能非常多人都会用不到.可是关于 ...

  8. Android Framework中的Application Framework层介绍

    Android的四层架构相比大家都很清楚,老生常谈的说一下分别为:Linux2.6内核层,核心库层,应用框架层,应用层.我今天重点介绍一下应用框架层Framework,其实也是我自己的学习心得. Fr ...

  9. Android开发中JavaBean类和序列化知识的理解

    原创文章,转载请注明出处:http://www.cnblogs.com/baipengzhan/p/6296121.html Android开发中,我们经常用到JavaBean类以及序列化的知识,但经 ...

随机推荐

  1. js中封装一个自己的简单数学对象

    封装一个数学对象求最大值最小值 <script> var myMath={ PI:3.1415926, max:function(){ var max=arguments[0];//注意a ...

  2. fpga错误总结

    Error (10200): Verilog HDL Conditional Statement error at ps2_con_cmd.v(11): cannot match operand(s) ...

  3. centos 7 安装相关环境

    How To Create a Sudo User on CentOS 7 https://www.digitalocean.com/community/tutorials/how-to-create ...

  4. [HTTP知识体系]前端常用的一些参数

    1.http常见状态码(status code) 200(成功) 服务器已成功处理了请求.通常,这表示服务器提供了请求的网页. 301 (永久移动) 请求的网页已永久移动到新位置. 服务器返回此响应( ...

  5. ASP.NET Core 基础知识(三) Program.cs类

    ASP.NET Framework应用程序是严重依赖于IIS的,System.Web 中有很多方法都是直接调用的 IIS API,并且它还是驻留在IIS进程中的.而 ASP.NET Core 的运行则 ...

  6. 【CF487E】Tourists

    洛谷链接 题意 给定一张无向图,点有点权,多次询问两点之间路径上点权最小的点的可能的最小值,支持修改点权. Sol 一棵树就很简单 , 于是我们考虑点双(环)上的情况 , 直观想法就是缩完点双后一个点 ...

  7. ESP8266的使用学习

     ESP8266-01  ESP8266-12F简介 让灯闪烁    ESP8266-中断   模拟输入(ADC-A0)  模拟输出(PWM)  串口通信(Serial)    EEPROM类库的使用 ...

  8. 关于mysql(Navicat premium软件中) 外键设置中“删除”和“更新”选项详解

    ON DELETE restrict(约束):当在父表(即外键的来源表)中删除对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除. no action:意思同restrict.即如果存在从数 ...

  9. eclipse设置maven web项目打包

    如图:eclipse下的maven web项目,打包部署到本地tomcat时,需要关注的2个方面: 1. src/main/webapp目录下的文件,打包到/ 根路径下 2. 添加maven 依赖,打 ...

  10. C# 基础:DataTable操作、发邮件

    本文出自:https://www.cnblogs.com/2186009311CFF/p/6865909.html DataTable操作 据参数删除为0的列:包括遍历.删除.取值 public st ...