<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>


    在操作系統中,有兩種不同的方法提供線程支持:用戶層的用戶線程,或內核層的內核線程。

    其中用戶線程在內核之上支持,并在用戶層通過線程庫來實現。不需要用戶態/核心態切換,速度快。操作系統內核不知道多線程的存在,因此一個線程阻塞將使得整個進程(包括它的所有線程)阻塞。由于這里的處理器時間片分配是以進程為基本單位,所以每個線程執行的時間相對減少。

    內核線程由操作系統直接支持。由操作系統內核創建、調度和管理。內核維護進程及線程的上下文信息以及線程切換。一個內核線程由于I/O操作而阻塞,不會影響其它線程的運行。

    Java線程的實現是怎樣的呢?我們通過SUN Java 6的源碼了解其在Windows和Linux下的實現。

    在Windows下的實現,os_win32.cpp中
    // Allocate and initialize a new OSThread
    bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
      unsigned thread_id;

      
    // Allocate the OSThread object
      OSThread* osthread = new OSThread(NULL, NULL);
      
    if (osthread == NULL) {
        
    return false;
      }

      
    // Initial state is ALLOCATED but not INITIALIZED
      {
        MutexLockerEx ml(thread
    ->SR_lock(), Mutex::_no_safepoint_check_flag);
        osthread
    ->set_state(ALLOCATED);
      }
      
      
    // Initialize support for Java interrupts
      HANDLE interrupt_event = CreateEvent(NULL, truefalse, NULL);
      
    if (interrupt_event == NULL) {
        delete osthread;
        
    return NULL;
      }
      osthread
    ->set_interrupt_event(interrupt_event);
      osthread
    ->set_interrupted(false);
      
      thread
    ->set_osthread(osthread);
      
      
    if (stack_size == 0) {
        
    switch (thr_type) {
        
    case os::java_thread:
          
    // Java threads use ThreadStackSize which default value can be changed with the flag -Xss
          if (JavaThread::stack_size_at_create() > 0)
            stack_size 
    = JavaThread::stack_size_at_create();
          
    break;
        
    case os::compiler_thread:
          
    if (CompilerThreadStackSize > 0) {
            stack_size 
    = (size_t)(CompilerThreadStackSize * K);
            
    break;
          } 
    // else fall through:
            
    // use VMThreadStackSize if CompilerThreadStackSize is not defined
        case os::vm_thread:
        
    case os::pgc_thread:
        
    case os::cgc_thread:
        
    case os::watcher_thread:
          
    if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K);
          
    break;
        }
      }

      
    // Create the Win32 thread
      
    //
      
    // Contrary to what MSDN document says, "stack_size" in _beginthreadex()
      
    // does not specify stack size. Instead, it specifies the size of
      
    // initially committed space. The stack size is determined by
      
    // PE header in the executable. If the committed "stack_size" is larger
      
    // than default value in the PE header, the stack is rounded up to the
      
    // nearest multiple of 1MB. For example if the launcher has default
      
    // stack size of 320k, specifying any size less than 320k does not
      
    // affect the actual stack size at all, it only affects the initial
      
    // commitment. On the other hand, specifying 'stack_size' larger than
      
    // default value may cause significant increase in memory usage, because
      
    // not only the stack space will be rounded up to MB, but also the
      
    // entire space is committed upfront.
      
    //
      
    // Finally Windows XP added a new flag 'STACK_SIZE_PARAM_IS_A_RESERVATION'
      
    // for CreateThread() that can treat 'stack_size' as stack size. However we
      
    // are not supposed to call CreateThread() directly according to MSDN
      
    // document because JVM uses C runtime library. The good news is that the
      
    // flag appears to work with _beginthredex() as well.

    #ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
    #define STACK_SIZE_PARAM_IS_A_RESERVATION  (0x10000)
    #endif

      HANDLE thread_handle 
    =
        (HANDLE)_beginthreadex(NULL,
                               (unsigned)stack_size,
                               (unsigned (__stdcall 
    *)(void*)) java_start,
                               thread,
                               CREATE_SUSPENDED 
    | STACK_SIZE_PARAM_IS_A_RESERVATION,
                               
    &thread_id);
      
    if (thread_handle == NULL) {
        
    // perhaps STACK_SIZE_PARAM_IS_A_RESERVATION is not supported, try again
        
    // without the flag.
        thread_handle =
        (HANDLE)_beginthreadex(NULL,
                               (unsigned)stack_size,
                               (unsigned (__stdcall 
    *)(void*)) java_start,
                               thread,
                               CREATE_SUSPENDED,
                               
    &thread_id);
      }
      
    if (thread_handle == NULL) {
        
    // Need to clean up stuff we've allocated so far
        CloseHandle(osthread->interrupt_event());
        thread
    ->set_osthread(NULL);
        delete osthread;
        
    return NULL;
      }
      
      Atomic::inc_ptr((intptr_t
    *)&os::win32::_os_thread_count);

      
    // Store info on the Win32 thread into the OSThread
      osthread->set_thread_handle(thread_handle);
      osthread
    ->set_thread_id(thread_id);

      
    // Initial thread state is INITIALIZED, not SUSPENDED
      {
        MutexLockerEx ml(thread
    ->SR_lock(), Mutex::_no_safepoint_check_flag);
        osthread
    ->set_state(INITIALIZED);
      }

      
    // The thread is returned suspended (in state INITIALIZED), and is started higher up in the call chain
      return true;
    }

    可以看出,SUN JVM在Windows下的實現,使用_beginthreadex來創建線程,注釋中也說明了為什么不用“Window編程書籍推薦使用”的CreateThread函數。由此看出,Java線程在Window下的實現是使用內核線程。

    而在Linux下又是怎樣的呢?

    在os_linux.cpp文件中的代碼摘錄如下:

    # include <pthread.h>

    bool
     os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
      assert(thread
    ->osthread() == NULL, "caller responsible");

      
    // Allocate the OSThread object
      OSThread* osthread = new OSThread(NULL, NULL);
      
    if (osthread == NULL) {
        
    return false;
      }

      
    // set the correct thread state
      osthread->set_thread_type(thr_type);

      
    // Initial state is ALLOCATED but not INITIALIZED
      osthread->set_state(ALLOCATED);

      thread
    ->set_osthread(osthread);

      
    // init thread attributes
      pthread_attr_t attr;
      pthread_attr_init(
    &attr);
      pthread_attr_setdetachstate(
    &attr, PTHREAD_CREATE_DETACHED);

      
    // stack size
      if (os::Linux::supports_variable_stack_size()) {
        
    // calculate stack size if it's not specified by caller
        if (stack_size == 0) {
          stack_size 
    = os::Linux::default_stack_size(thr_type);

          
    switch (thr_type) {
          
    case os::java_thread:
            
    // Java threads use ThreadStackSize which default value can be changed with the flag -Xss
            if (JavaThread::stack_size_at_create() > 0) stack_size = JavaThread::stack_size_at_create();
            
    break;
          
    case os::compiler_thread:
            
    if (CompilerThreadStackSize > 0) {
              stack_size 
    = (size_t)(CompilerThreadStackSize * K);
              
    break;
            } 
    // else fall through:
              
    // use VMThreadStackSize if CompilerThreadStackSize is not defined
          case os::vm_thread: 
          
    case os::pgc_thread: 
          
    case os::cgc_thread: 
          
    case os::watcher_thread: 
            
    if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K);
            
    break;
          }
        }

        stack_size 
    = MAX2(stack_size, os::Linux::min_stack_allowed);
        pthread_attr_setstacksize(
    &attr, stack_size);
      } 
    else {
        
    // let pthread_create() pick the default value.
      }

      
    // glibc guard page
      pthread_attr_setguardsize(&attr, os::Linux::default_guard_size(thr_type));

      ThreadState state;

      {
        
    // Serialize thread creation if we are running with fixed stack LinuxThreads
        bool lock = os::Linux::is_LinuxThreads() && !os::Linux::is_floating_stack();
        
    if (lock) {
          os::Linux::createThread_lock()
    ->lock_without_safepoint_check();
        }

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

        pthread_attr_destroy(
    &attr);

        
    if (ret != 0) {
          
    if (PrintMiscellaneous && (Verbose || WizardMode)) {
            perror(
    "pthread_create()");
          }
          
    // Need to clean up stuff we've allocated so far
          thread->set_osthread(NULL);
          delete osthread;
          
    if (lock) os::Linux::createThread_lock()->unlock();
          
    return false;
        }

        
    // Store pthread info into the OSThread
        osthread->set_pthread_id(tid);

        
    // Wait until child thread is either initialized or aborted
        {
          Monitor
    * sync_with_child = osthread->startThread_lock();
          MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);
          
    while ((state = osthread->get_state()) == ALLOCATED) {
            sync_with_child
    ->wait(Mutex::_no_safepoint_check_flag);
          }
        }

        
    if (lock) {
          os::Linux::createThread_lock()
    ->unlock();
        }
      }

      
    // Aborted due to thread limit being reached
      if (state == ZOMBIE) {
          thread
    ->set_osthread(NULL);
          delete osthread;
          
    return false;
      }

      
    // The thread is returned suspended (in state INITIALIZED),
      
    // and is started higher up in the call chain
      assert(state == INITIALIZED, "race condition");
      
    return true;
    }

    Java在Linux下的線程的創建,使用了pthread線程庫,而pthread就是一個用戶線程庫,因此結論是,Java在Linux下是使用用戶線程實現的。





    溫少 2007-04-18 05:28 發表評論
    posted on 2007-04-18 05:28 溫少的日志 閱讀(943) 評論(4)  編輯  收藏
    Comments
    • # re: 關于Java線程的實現
      Tony Xu
      Posted @ 2007-04-19 11:27
      不敢茍同“因此一個線程阻塞將使得整個進程(包括它的所有線程)阻塞”,Linux用戶線程和內核線程是1:1對應的  回復  更多評論   
    • # re: 關于Java線程的實現
      溫少的日志
      Posted @ 2007-04-22 03:57
      其實偶不是很清楚Linux下pthread的最終實現,看過資料,說pthread是用戶線程庫。

      在solaris下,pthread的用戶線程和內核線程影射,是多對多的。

      Windows下Fiber也可以實現多對多。

      linux下的實現,我了解還不多,2.6在線程支持方面有重大變化,但偶還沒花時間去學習。  回復  更多評論   
    • # re: 關于Java線程的實現
      溫少的日志
      Posted @ 2007-04-22 11:45
      在Linux下使用Firefox、Eclipse等軟件,當某個操作阻塞的時候,整個程序甚至整個Gnome桌面會停止響應。

      這一現象和用戶線程出現阻塞的現象吻合。

      使用Ubuntu工作一段時間了,說實在,沒有在Windows XP下流暢。

      同一臺機器上,Eclipse跑在Windows XP下的性能比Ubuntu LInux下快多了,在Linux下,經常出現某個操作阻塞時,整個Eclipse失去響應,而在Windows下,很少出現這種情況。  回復  更多評論   
    • # re: 關于Java線程的實現
      larz
      Posted @ 2007-04-25 06:20
      在linux下使用使用firefox、eclipse感到緩慢、回應性差的主要原因,在于底層的gtk+和cairo的效能問題,這點在firefox的使用者群組已經被提出很多次,我推測使用gtk+繪制介面的eclipse也是相同原因。  回復  更多評論   

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
     
    主站蜘蛛池模板: 亚洲综合小说久久另类区| 好吊妞998视频免费观看在线| 免费一级毛片不卡在线播放| 亚洲综合无码无在线观看| 噼里啪啦电影在线观看免费高清| 亚洲美女色在线欧洲美女| 久久精品免费观看国产| 亚洲精品无码乱码成人| 免费精品久久天干天干| 亚洲AV综合色区无码一区爱AV| 亚洲视频免费观看| 亚洲人成无码网站在线观看| 日本片免费观看一区二区| 亚洲短视频在线观看| 免费影院未满十八勿进网站| 亚洲avav天堂av在线网爱情| 午夜宅男在线永久免费观看网| 成人亚洲国产va天堂| 最近中文字幕免费mv视频7| 亚洲av永久中文无码精品综合 | 久久精品国产亚洲AV不卡| 一边摸一边爽一边叫床免费视频| 日韩一卡2卡3卡4卡新区亚洲| 国产免费AV片在线观看| 亚洲欧洲高清有无| 韩国欧洲一级毛片免费| 皇色在线免费视频| 久久久久久亚洲Av无码精品专口 | 中国毛片免费观看| 亚洲视频在线观看网址| 精品国产麻豆免费网站 | 东北美女野外bbwbbw免费| 亚洲国产香蕉碰碰人人| 成年午夜视频免费观看视频| 美女被免费视频网站a| 亚洲国产精品乱码一区二区| 在人线av无码免费高潮喷水| 免费的黄色的网站| 91精品国产亚洲爽啪在线观看| 日韩免费在线观看| 免费黄网站在线看|