innnodb 线程在做什么?

1.master 线程的主代码位于
   (1)storage/innobase/srv/srv0srv.cc
   (2)storage/innobase/buf/buf0flu.cc

   srv_master_do_idle_task()每10秒中的操作。
   srv_master_do_active_tasks()每秒中的操作。

  1秒中的算法做的事情(主循环):
    (1)日志刷新到磁盘,即使这个事务没有提交(总是)
    (2)合并插入缓冲(可能)
       //(3)至多刷新innodb_io_capacity个innodb的缓冲池中的脏页到磁盘(可能) ---innodb新版本中已经交给了page_cleaner线程
    (4)如果没有用户活动,切换到background loop(可能)
  10秒中的算法做的事情(主循环):
    (1)刷新innodb_io_capacity个脏页到从盘(可能)
    (2)合并至多innodb_io_capacity*5%个插入缓冲(总是)
    (3)将日志缓冲刷新到磁盘(总是)
      //(4)刷新100个或者10个脏页到磁盘(总是)---innodb新版本中已经交给了page_cleaner线程
  切换到background loop做的事情:
    (1)删除innodb_purge_batch_size个无用的undo页(总是)
    (2)合并innodb_io_capacity*5%个插入缓冲(总是)
    (3)跳回到主循环(总是)
      //(4)不断刷新innodb_io_capacity个页直到符合条件---innodb新版本中已经交给了page_cleaner线程

mysql5.6后台线程:
+-----------+----------------------------------------+------------+
| thread_id | name                                   | type       |
+-----------+----------------------------------------+------------+
|         1 | thread/sql/main                        | BACKGROUND |
|         2 | thread/innodb/io_handler_thread        | BACKGROUND |
|         3 | thread/innodb/io_handler_thread        | BACKGROUND |
|         4 | thread/innodb/io_handler_thread        | BACKGROUND |
|         5 | thread/innodb/io_handler_thread        | BACKGROUND |
|         6 | thread/innodb/io_handler_thread        | BACKGROUND |
|         7 | thread/innodb/io_handler_thread        | BACKGROUND |
|         8 | thread/innodb/io_handler_thread        | BACKGROUND |
|         9 | thread/innodb/io_handler_thread        | BACKGROUND |
|        10 | thread/innodb/io_handler_thread        | BACKGROUND |
|        11 | thread/innodb/io_handler_thread        | BACKGROUND |
|        14 | thread/innodb/srv_master_thread        | BACKGROUND |
|        15 | thread/innodb/srv_monitor_thread       | BACKGROUND |
|        16 | thread/innodb/srv_purge_thread         | BACKGROUND | --undo页回收线程
|        17 | thread/innodb/srv_error_monitor_thread | BACKGROUND |
|        18 | thread/innodb/srv_lock_timeout_thread  | BACKGROUND |
|        19 | thread/innodb/page_cleaner_thread      | BACKGROUND | --刷新脏页线程
|        20 | thread/sql/signal_handler              | BACKGROUND |
+-----------+----------------------------------------+------------+
storage/innobase/buf/buf0flu.cc:

/******************************************************************//**
page_cleaner thread tasked with flushing dirty pages from the buffer
pools. As of now we‘ll have only one instance of this thread.
@return a dummy parameter */
extern "C" UNIV_INTERN
os_thread_ret_t
DECLARE_THREAD(buf_flush_page_cleaner_thread)(
/*==========================================*/
    void*    arg __attribute__((unused)))
            /*!< in: a dummy parameter required by
            os_thread_create */
{
    ulint    next_loop_time = ut_time_ms() + 1000;
    ulint    n_flushed = 0;
    ulint    last_activity = srv_get_activity_count();

    ut_ad(!srv_read_only_mode);

#ifdef UNIV_PFS_THREAD
    pfs_register_thread(buf_page_cleaner_thread_key);
#endif /* UNIV_PFS_THREAD */

#ifdef UNIV_DEBUG_THREAD_CREATION
    fprintf(stderr, "InnoDB: page_cleaner thread running, id %lu\n",
        os_thread_pf(os_thread_get_curr_id()));
#endif /* UNIV_DEBUG_THREAD_CREATION */

    buf_page_cleaner_is_active = TRUE;

    while (srv_shutdown_state == SRV_SHUTDOWN_NONE) {

        /* The page_cleaner skips sleep if the server is
        idle and there are no pending IOs in the buffer pool
        and there is work to do. */
        if (srv_check_activity(last_activity)
            || buf_get_n_pending_read_ios()
            || n_flushed == 0) {
            page_cleaner_sleep_if_needed(next_loop_time);
        }

        next_loop_time = ut_time_ms() + 1000;

        if (srv_check_activity(last_activity)) {
            last_activity = srv_get_activity_count();

            /* Flush pages from end of LRU if required */
            n_flushed = buf_flush_LRU_tail();

            /* Flush pages from flush_list if required */
            n_flushed += page_cleaner_flush_pages_if_needed();
        } else {
            n_flushed = page_cleaner_do_flush_batch(
                            PCT_IO(100),
                            LSN_MAX);

            if (n_flushed) {
                MONITOR_INC_VALUE_CUMULATIVE(
                    MONITOR_FLUSH_BACKGROUND_TOTAL_PAGE,
                    MONITOR_FLUSH_BACKGROUND_COUNT,
                    MONITOR_FLUSH_BACKGROUND_PAGES,
                    n_flushed);
            }
        }
    }

    ut_ad(srv_shutdown_state > 0);
    if (srv_fast_shutdown == 2) {
        /* In very fast shutdown we simulate a crash of
        buffer pool. We are not required to do any flushing */
        goto thread_exit;
    }

    /* In case of normal and slow shutdown the page_cleaner thread
    must wait for all other activity in the server to die down.
    Note that we can start flushing the buffer pool as soon as the
    server enters shutdown phase but we must stay alive long enough
    to ensure that any work done by the master or purge threads is
    also flushed.
    During shutdown we pass through two stages. In the first stage,
    when SRV_SHUTDOWN_CLEANUP is set other threads like the master
    and the purge threads may be working as well. We start flushing
    the buffer pool but can‘t be sure that no new pages are being
    dirtied until we enter SRV_SHUTDOWN_FLUSH_PHASE phase. */

    do {
        n_flushed = page_cleaner_do_flush_batch(PCT_IO(100), LSN_MAX);

        /* We sleep only if there are no pages to flush */
        if (n_flushed == 0) {
            os_thread_sleep(100000);
        }
    } while (srv_shutdown_state == SRV_SHUTDOWN_CLEANUP);

    /* At this point all threads including the master and the purge
    thread must have been suspended. */
    ut_a(srv_get_active_thread_type() == SRV_NONE);
    ut_a(srv_shutdown_state == SRV_SHUTDOWN_FLUSH_PHASE);

    /* We can now make a final sweep on flushing the buffer pool
    and exit after we have cleaned the whole buffer pool.
    It is important that we wait for any running batch that has
    been triggered by us to finish. Otherwise we can end up
    considering end of that batch as a finish of our final
    sweep and we‘ll come out of the loop leaving behind dirty pages
    in the flush_list */
    buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
    buf_flush_wait_LRU_batch_end();

    bool    success;

    do {

        success = buf_flush_list(PCT_IO(100), LSN_MAX, &n_flushed);
        buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);

    } while (!success || n_flushed > 0);

    /* Some sanity checks */
    ut_a(srv_get_active_thread_type() == SRV_NONE);
    ut_a(srv_shutdown_state == SRV_SHUTDOWN_FLUSH_PHASE);
    for (ulint i = 0; i < srv_buf_pool_instances; i++) {
        buf_pool_t* buf_pool = buf_pool_from_array(i);
        ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == 0);
    }

    /* We have lived our life. Time to die. */

thread_exit:
    buf_page_cleaner_is_active = FALSE;

    /* We count the number of threads in os_thread_exit(). A created
    thread should always use that to exit and not use return() to exit. */
    os_thread_exit(NULL);

    OS_THREAD_DUMMY_RETURN;
}

/*********************************************************************//**
This function is called approximately once every second by the
page_cleaner thread. Based on various factors it decides if there is a
need to do flushing. If flushing is needed it is performed and the
number of pages flushed is returned.
@return number of pages flushed */
static
ulint
page_cleaner_flush_pages_if_needed(void)
/*====================================*/
{
    static    lsn_t        lsn_avg_rate = 0;
    static    lsn_t        prev_lsn = 0;
    static    lsn_t        last_lsn = 0;
    static    ulint        sum_pages = 0;
    static    ulint        last_pages = 0;
    static    ulint        prev_pages = 0;
    static    ulint        avg_page_rate = 0;
    static    ulint        n_iterations = 0;
    lsn_t            oldest_lsn;
    lsn_t            cur_lsn;
    lsn_t            age;
    lsn_t            lsn_rate;
    ulint            n_pages = 0;
    ulint            pct_for_dirty = 0;
    ulint            pct_for_lsn = 0;
    ulint            pct_total = 0;
    int            age_factor = 0;

    cur_lsn = log_get_lsn();

    if (prev_lsn == 0) {
        /* First time around. */
        prev_lsn = cur_lsn;
        return(0);
    }

    if (prev_lsn == cur_lsn) {
        return(0);
    }

    /* We update our variables every srv_flushing_avg_loops
    iterations to smooth out transition in workload. */
    if (++n_iterations >= srv_flushing_avg_loops) {

        avg_page_rate = ((sum_pages / srv_flushing_avg_loops)
                 + avg_page_rate) / 2;

        /* How much LSN we have generated since last call. */
        lsn_rate = (cur_lsn - prev_lsn) / srv_flushing_avg_loops;

        lsn_avg_rate = (lsn_avg_rate + lsn_rate) / 2;

        prev_lsn = cur_lsn;

        n_iterations = 0;

        sum_pages = 0;
    }

    oldest_lsn = buf_pool_get_oldest_modification();

    ut_ad(oldest_lsn <= log_get_lsn());

    age = cur_lsn > oldest_lsn ? cur_lsn - oldest_lsn : 0;

    pct_for_dirty = af_get_pct_for_dirty();
    pct_for_lsn = af_get_pct_for_lsn(age);

    pct_total = ut_max(pct_for_dirty, pct_for_lsn);

    /* Cap the maximum IO capacity that we are going to use by
    max_io_capacity. */
    n_pages = (PCT_IO(pct_total) + avg_page_rate) / 2;

    if (n_pages > srv_max_io_capacity) {
        n_pages = srv_max_io_capacity;
    }

    if (last_pages && cur_lsn - last_lsn > lsn_avg_rate / 2) {
        age_factor = prev_pages / last_pages;
    }

    MONITOR_SET(MONITOR_FLUSH_N_TO_FLUSH_REQUESTED, n_pages);

    prev_pages = n_pages;
    n_pages = page_cleaner_do_flush_batch(
        n_pages, oldest_lsn + lsn_avg_rate * (age_factor + 1));

    last_lsn= cur_lsn;
    last_pages= n_pages + 1;

    MONITOR_SET(MONITOR_FLUSH_AVG_PAGE_RATE, avg_page_rate);
    MONITOR_SET(MONITOR_FLUSH_LSN_AVG_RATE, lsn_avg_rate);
    MONITOR_SET(MONITOR_FLUSH_PCT_FOR_DIRTY, pct_for_dirty);
    MONITOR_SET(MONITOR_FLUSH_PCT_FOR_LSN, pct_for_lsn);

    if (n_pages) {
        MONITOR_INC_VALUE_CUMULATIVE(
            MONITOR_FLUSH_ADAPTIVE_TOTAL_PAGE,
            MONITOR_FLUSH_ADAPTIVE_COUNT,
            MONITOR_FLUSH_ADAPTIVE_PAGES,
            n_pages);

        sum_pages += n_pages;
    }

    return(n_pages);
}

storage/innobase/srv/srv0srv.c:

/*********************************************************************//**
Perform the tasks that the master thread is supposed to do when the
server is active. There are two types of tasks. The first category is
of such tasks which are performed at each inovcation of this function.
We assume that this function is called roughly every second when the
server is active. The second category is of such tasks which are
performed at some interval e.g.: purge, dict_LRU cleanup etc. */
static
void
srv_master_do_active_tasks(void)
/*============================*/
{
    ib_time_t    cur_time = ut_time();
    ullint        counter_time = ut_time_us(NULL);

    /* First do the tasks that we are suppose to do at each
    invocation of this function. */

    ++srv_main_active_loops;

    MONITOR_INC(MONITOR_MASTER_ACTIVE_LOOPS);

    /* ALTER TABLE in MySQL requires on Unix that the table handler
    can drop tables lazily after there no longer are SELECT
    queries to them. */
    srv_main_thread_op_info = "doing background drop tables";
    row_drop_tables_for_mysql_in_background();
    MONITOR_INC_TIME_IN_MICRO_SECS(
        MONITOR_SRV_BACKGROUND_DROP_TABLE_MICROSECOND, counter_time);

    if (srv_shutdown_state > 0) {
        return;
    }

    /* make sure that there is enough reusable space in the redo
    log files */
    srv_main_thread_op_info = "checking free log space";
    log_free_check();

    /* Do an ibuf merge */
    srv_main_thread_op_info = "doing insert buffer merge";
    counter_time = ut_time_us(NULL);
    ibuf_contract_in_background(0, FALSE);
    MONITOR_INC_TIME_IN_MICRO_SECS(
        MONITOR_SRV_IBUF_MERGE_MICROSECOND, counter_time);

    /* Flush logs if needed */
    srv_main_thread_op_info = "flushing log";
    srv_sync_log_buffer_in_background();
    MONITOR_INC_TIME_IN_MICRO_SECS(
        MONITOR_SRV_LOG_FLUSH_MICROSECOND, counter_time);

    /* Now see if various tasks that are performed at defined
    intervals need to be performed. */

#ifdef MEM_PERIODIC_CHECK
    /* Check magic numbers of every allocated mem block once in
    SRV_MASTER_MEM_VALIDATE_INTERVAL seconds */
    if (cur_time % SRV_MASTER_MEM_VALIDATE_INTERVAL == 0) {
        mem_validate_all_blocks();
        MONITOR_INC_TIME_IN_MICRO_SECS(
            MONITOR_SRV_MEM_VALIDATE_MICROSECOND, counter_time);
    }
#endif
    if (srv_shutdown_state > 0) {
        return;
    }

    if (srv_shutdown_state > 0) {
        return;
    }

    if (cur_time % SRV_MASTER_DICT_LRU_INTERVAL == 0) {
        srv_main_thread_op_info = "enforcing dict cache limit";
        srv_master_evict_from_table_cache(50);
        MONITOR_INC_TIME_IN_MICRO_SECS(
            MONITOR_SRV_DICT_LRU_MICROSECOND, counter_time);
    }

    if (srv_shutdown_state > 0) {
        return;
    }

    /* Make a new checkpoint */
    if (cur_time % SRV_MASTER_CHECKPOINT_INTERVAL == 0) {
        srv_main_thread_op_info = "making checkpoint";
        log_checkpoint(TRUE, FALSE);
        MONITOR_INC_TIME_IN_MICRO_SECS(
            MONITOR_SRV_CHECKPOINT_MICROSECOND, counter_time);
    }
}

/*********************************************************************//**
Perform the tasks that the master thread is supposed to do whenever the
server is idle. We do check for the server state during this function
and if the server has entered the shutdown phase we may return from
the function without completing the required tasks.
Note that the server can move to active state when we are executing this
function but we don‘t check for that as we are suppose to perform more
or less same tasks when server is active. */
static
void
srv_master_do_idle_tasks(void)
/*==========================*/
{
    ullint    counter_time;

    ++srv_main_idle_loops;

    MONITOR_INC(MONITOR_MASTER_IDLE_LOOPS);

    /* ALTER TABLE in MySQL requires on Unix that the table handler
    can drop tables lazily after there no longer are SELECT
    queries to them. */
    counter_time = ut_time_us(NULL);
    srv_main_thread_op_info = "doing background drop tables";
    row_drop_tables_for_mysql_in_background();
    MONITOR_INC_TIME_IN_MICRO_SECS(
        MONITOR_SRV_BACKGROUND_DROP_TABLE_MICROSECOND,
             counter_time);

    if (srv_shutdown_state > 0) {
        return;
    }

    /* make sure that there is enough reusable space in the redo
    log files */
    srv_main_thread_op_info = "checking free log space";
    log_free_check();

    /* Do an ibuf merge */
    counter_time = ut_time_us(NULL);
    srv_main_thread_op_info = "doing insert buffer merge";
    ibuf_contract_in_background(0, TRUE);
    MONITOR_INC_TIME_IN_MICRO_SECS(
        MONITOR_SRV_IBUF_MERGE_MICROSECOND, counter_time);

    if (srv_shutdown_state > 0) {
        return;
    }

    srv_main_thread_op_info = "enforcing dict cache limit";
    srv_master_evict_from_table_cache(100);
    MONITOR_INC_TIME_IN_MICRO_SECS(
        MONITOR_SRV_DICT_LRU_MICROSECOND, counter_time);

    /* Flush logs if needed */
    srv_sync_log_buffer_in_background();
    MONITOR_INC_TIME_IN_MICRO_SECS(
        MONITOR_SRV_LOG_FLUSH_MICROSECOND, counter_time);

    if (srv_shutdown_state > 0) {
        return;
    }

    /* Make a new checkpoint */
    srv_main_thread_op_info = "making checkpoint";
    log_checkpoint(TRUE, FALSE);
    MONITOR_INC_TIME_IN_MICRO_SECS(MONITOR_SRV_CHECKPOINT_MICROSECOND,
                       counter_time);
}

/*********************************************************************//**
Perform the tasks during shutdown. The tasks that we do at shutdown
depend on srv_fast_shutdown:
2 => very fast shutdown => do no book keeping
1 => normal shutdown => clear drop table queue and make checkpoint
0 => slow shutdown => in addition to above do complete purge and ibuf
merge
@return TRUE if some work was done. FALSE otherwise */
static
ibool
srv_master_do_shutdown_tasks(
/*=========================*/
    ib_time_t*    last_print_time)/*!< last time the function
                    print the message */
{
    ulint        n_bytes_merged = 0;
    ulint        n_tables_to_drop = 0;

    ut_ad(!srv_read_only_mode);

    ++srv_main_shutdown_loops;

    ut_a(srv_shutdown_state > 0);

    /* In very fast shutdown none of the following is necessary */
    if (srv_fast_shutdown == 2) {
        return(FALSE);
    }

    /* ALTER TABLE in MySQL requires on Unix that the table handler
    can drop tables lazily after there no longer are SELECT
    queries to them. */
    srv_main_thread_op_info = "doing background drop tables";
    n_tables_to_drop = row_drop_tables_for_mysql_in_background();

    /* make sure that there is enough reusable space in the redo
    log files */
    srv_main_thread_op_info = "checking free log space";
    log_free_check();

    /* In case of normal shutdown we don‘t do ibuf merge or purge */
    if (srv_fast_shutdown == 1) {
        goto func_exit;
    }

    /* Do an ibuf merge */
    srv_main_thread_op_info = "doing insert buffer merge";
    n_bytes_merged = ibuf_contract_in_background(0, TRUE);

    /* Flush logs if needed */
    srv_sync_log_buffer_in_background();

func_exit:
    /* Make a new checkpoint about once in 10 seconds */
    srv_main_thread_op_info = "making checkpoint";
    log_checkpoint(TRUE, FALSE);

    /* Print progress message every 60 seconds during shutdown */
    if (srv_shutdown_state > 0 && srv_print_verbose_log) {
        srv_shutdown_print_master_pending(
            last_print_time, n_tables_to_drop, n_bytes_merged);
    }

    return(n_bytes_merged || n_tables_to_drop);
}

/*********************************************************************//**
Puts master thread to sleep. At this point we are using polling to
service various activities. Master thread sleeps for one second before
checking the state of the server again */
static
void
srv_master_sleep(void)
/*==================*/
{
    srv_main_thread_op_info = "sleeping";
    os_thread_sleep(1000000);
    srv_main_thread_op_info = "";
}

/*********************************************************************//**
The master thread controlling the server.
@return    a dummy parameter */
extern "C" UNIV_INTERN
os_thread_ret_t
DECLARE_THREAD(srv_master_thread)(
/*==============================*/
    void*    arg __attribute__((unused)))
            /*!< in: a dummy parameter required by
            os_thread_create */
{
    srv_slot_t*    slot;
    ulint        old_activity_count = srv_get_activity_count();
    ib_time_t    last_print_time;

    ut_ad(!srv_read_only_mode);

#ifdef UNIV_DEBUG_THREAD_CREATION
    fprintf(stderr, "Master thread starts, id %lu\n",
        os_thread_pf(os_thread_get_curr_id()));
#endif /* UNIV_DEBUG_THREAD_CREATION */

#ifdef UNIV_PFS_THREAD
    pfs_register_thread(srv_master_thread_key);
#endif /* UNIV_PFS_THREAD */

    srv_main_thread_process_no = os_proc_get_number();
    srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());

    slot = srv_reserve_slot(SRV_MASTER);
    ut_a(slot == srv_sys->sys_threads);

    last_print_time = ut_time();
loop:
    if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
        goto suspend_thread;
    }

    while (srv_shutdown_state == SRV_SHUTDOWN_NONE) {

        srv_master_sleep();

        MONITOR_INC(MONITOR_MASTER_THREAD_SLEEP);

        if (srv_check_activity(old_activity_count)) {
            old_activity_count = srv_get_activity_count();
            srv_master_do_active_tasks();
        } else {
            srv_master_do_idle_tasks();
        }
    }

    while (srv_master_do_shutdown_tasks(&last_print_time)) {

        /* Shouldn‘t loop here in case of very fast shutdown */
        ut_ad(srv_fast_shutdown < 2);
    }

suspend_thread:
    srv_main_thread_op_info = "suspending";

    srv_suspend_thread(slot);

    /* DO NOT CHANGE THIS STRING. innobase_start_or_create_for_mysql()
    waits for database activity to die down when converting < 4.1.x
    databases, and relies on this string being exactly as it is. InnoDB
    manual also mentions this string in several places. */
    srv_main_thread_op_info = "waiting for server activity";

    os_event_wait(slot->event);

    if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
        os_thread_exit(NULL);
    }

    goto loop;

    OS_THREAD_DUMMY_RETURN;    /* Not reached, avoid compiler warning */
}
时间: 2024-10-24 19:51:33

innnodb 线程在做什么?的相关文章

为什么子线程不能做UI操作

在子线程中是不能进行UI 更新的,而可以更新的结果只是一个幻像:因为子线程代码执行完毕了,又自动进入到了主线程,执行了子线程中的UI更新的函数栈,这中间的时间非常的短,就 让大家误以为分线程可以更新UI.如果子线程一直在运行,则子线程中的UI更新的函数栈 主线程无法获知,即无法更新 参考:http://blog.sina.com.cn/s/blog_45e2b66c0102v254.html

用service在后台开线程+广播做一个计时器

1.首先写一个服务,在onStartCommand方法里开启线程,每次startService就会调一次onStartCommand方法 import java.util.List; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.

webview加载页面为什么在UI线程里面做,难道不是耗时操作么

============问题描述============ 谁能告诉我 想不明白 ============解决方案1============ WebView 里面必须放在UI线程里面展示. private static void checkThread() { if (Looper.myLooper() != Looper.getMainLooper()) { Throwable throwable = new Throwable( "Warning: A WebView method was c

【Simple Java】面试问题-使用Java线程做数学运算

这是一个展示如何使用join()方法的例子. 问题: 使用Java多线程计算表达式1*2/(1+2)的值. 解决方案: 使用一个线程做加法运算,另一个线程做乘法运算,还有一个主线程main做除法运算.由于线程之间不需要通讯,所以我们只需要考虑线程的执行顺序. 在main线程中,我们让加法运算线程和乘法运算线程join到主线程,join()方法的作用是使main方法等待,直到调用join的线程执行完毕.在这个例子中,我们希望加法运算线程和乘法运算线程先结束,然后在计算除法运算. package s

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

首先回顾一下我们的基础知识. sleep: 线程睡眠,不会释放锁 wait: 线程等待.释放锁. notity: 唤醒随机一个当前对象等待的线程,并不会释放锁 notityAll: 唤醒所有当前对象等待的线程,并不会释放锁 遇到问题: 代码如下: package com.zhen.ten_chapter.question; /** * @author zhen * @Date 2019/4/18 10:17 */ public class ThreadDemo { public static v

POSIX 线程详解(经典必看)

总共三部分: 第一部分:POSIX 线程详解                                   Daniel Robbins ([email protected]), 总裁/CEO, Gentoo Technologies, Inc.  2000 年 7 月 01 日 第二部分:通用线程:POSIX 线程详解,第 2部分       Daniel Robbins ([email protected]), 总裁/CEO, Gentoo Technologies, Inc.  20

JAVA面试中问及HIBERNATE与 MYBATIS的对比,在这里做一下总结(转)

hibernate以及mybatis都有过学习,在java面试中也被提及问道过,在项目实践中也应用过,现在对hibernate和mybatis做一下对比,便于大家更好的理解和学习,使自己在做项目中更加得心应手. 第一方面:开发速度的对比 就开发速度而言,Hibernate的真正掌握要比Mybatis来得难些.Mybatis框架相对简单很容易上手,但也相对简陋些.个人觉得要用好Mybatis还是首先要先理解好Hibernate. 比起两者的开发速度,不仅仅要考虑到两者的特性及性能,更要根据项目需求

iOS多线程开发(二)---线程管理

线程管理 线程管理包括创建,配置,退出三部分.主要包括创建线程的成本,线程创建,线程属性配置,线程主体入口函数编写,线程中断等 一,线程创建成本 1,为辅助线程分配的堆栈空间大小,便于系统和进程管理,以及为函数参数和局部变量分配空间 A,内核数据结构(kernel data structures)---大约1KB,This memory is used to store the thread data structures and attributes, much of which is all

Python--day9--进程/线程/协程

 介绍 学习记录 2016年12月29日 19:36:23 目录: 进程/线程基础概念 GIL Join  &  Daemon 线程锁 RLock递归锁 信号量 Event Queques 进程 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本:进程是程序的一次执行活动,属于动态概念. 线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.