pthread_cond_wait

?

1. 首先pthread_cond_wait 的定義是這樣的

The pthread_cond_wait() andpthread_cond_timedwait() functions are used to block on a condition variable. They are called withmutex locked by the calling thread or undefined behaviour will result.

These functions atomically releasemutex and cause the calling thread to block on the condition variablecond ; atomically here means "atomically with respect to access by another thread to the mutex and then the condition variable". That is, if another thread is able to acquire the mutex after the about-to-block thread has released it, then a subsequent call topthread_cond_signal()orpthread_cond_broadcast()in that thread behaves as if it were issued after the about-to-block thread has blocked.

2. 由上解釋可以看出,pthread_cond_wait() 必須與pthread_mutex 配套使用。

pthread_cond_wait()函數一進入wait狀態就會自動release mutex.

In Thread1:

pthread_mutex_lock(&m_mutex);???
pthread_cond_wait(&m_cond,&m_mutex);???
pthread_mutex_unlock(&m_mutex);??

In Thread2:

pthread_mutex_lock(&m_mutex);???
pthread_cond_signal(&m_cond);???
pthread_mutex_unlock(&m_mutex);??

為什么要與pthread_mutex 一起使用呢?這是為了應對線程1在調用pthread_cond_wait()但線程1還沒有進入wait cond的狀態的時候,此時線程2調用了 cond_singal 的情況。 如果不用mutex鎖的話,這個cond_singal就丟失了。加了鎖的情況是,線程2必須等到 mutex 被釋放(也就是 pthread_cod_wait() 進入wait_cond狀態 并自動釋放mutex) 的時候才能調用cond_singal.

3. pthread_cond_wait() 一旦wait成功獲得cond 條件的時候會自動 lock mutex.

這就會出現另一個問題。這是因為

The pthread_cond_wait() andpthread_cond_timedwait() is a cancellation point.

In Thread3:

pthread_cancel(&m_thread);

pthread_join();

因為pthread_cond_wait() andpthread_cond_timedwait() ?? 是線程退出點函數,因此在Thread3中

可以調用pthread_cancel()來退出線程1。那樣顯然線程1會在 pthread_cond_wait(&m_cond,&m_mutex);??? 和 pthread_mutex_unlock(&m_mutex); 之間退出,??? pthread_cond_wait() 函數返回后自動lock住了mutex, 這個時候線程1退出(并沒有運行到pthread_mutex_unlock()),如果Thread2這個時候就再也得不到lock狀態了。

通常解決這個問題的辦法如下

void cleanup(void *arg)
{
?? pthread_mutex_unlock(&mutex);
}
void * thread1(void * arg)
{
??? pthread_cleanup_push(cleanup, NULL); // thread cleanup handler
??? pthread_mutex_lock(&mutex);
?? pthread_cond_wait(&cond, &mutex);
?? pthread_mutex_unlock(&mutex);
?? pthread_cleanup_pop(0 );
}




LINUX環境下多線程編程肯定會遇到需要條件變量的情況,此時必然要使用pthread_cond_wait()函數。但這個函數的執行過程比較難于理解。
??? pthread_cond_wait()的工作流程如下(以MAN中的EXAMPLE為例):
?????? Consider two shared variables x and y, protected by the mutex mut, and a condition vari-
?????? able cond that is to be signaled whenever x becomes greater than y.

????????????? int x,y;
????????????? pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
????????????? pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

?????? Waiting until x is greater than y is performed as follows:

????????????? pthread_mutex_lock(&mut);
????????????? while (x <= y) {
????????????????????? pthread_cond_wait(&cond, &mut);
????????????? }
????????????? /* operate on x and y */
????????????? pthread_mutex_unlock(&mut);

?????? Modifications on x and y that may cause x to become greater than y should signal the con-
?????? dition if needed:

????????????? pthread_mutex_lock(&mut);
????????????? /* modify x and y */
????????????? if (x > y) pthread_cond_broadcast(&cond);
????????????? pthread_mutex_unlock(&mut);

????這個例子的意思是,兩個線程要修改X和 Y的值,第一個線程當X<=Y時就掛起,直到X>Y時才繼續執行(由第二個線程可能會修改X,Y的值,當X>Y時喚醒第一個線程),即首先初始化一個普通互斥量mut和一個條件變量cond。之后分別在兩個線程中分別執行如下函數體:

?????????????pthread_mutex_lock(&mut);
????????????? while (x <= y) {
????????????????????? pthread_cond_wait(&cond, &mut);
????????????? }
????????????? /* operate on x and y */
????????????? pthread_mutex_unlock(&mut);

和:?????? pthread_mutex_lock(&mut);
????????????? /* modify x and y */
????????????? if (x > y) pthread_cond_signal(&cond);
????????????? pthread_mutex_unlock(&mut);

??? 其實函數的執行過程非常簡單,在第一個線程執行到pthread_cond_wait(&cond,&mut)時,此時如果X<=Y,則此函數就將mut互斥量解鎖 ,再將cond條件變量加鎖 ,此時第一個線程掛起 (不占用任何CPU周期)。
??? 而在第二個線程中,本來因為mut被第一個線程鎖住而阻塞,此時因為mut已經釋放,所以可以獲得鎖mut,并且進行修改X和Y的值,在修改之后,一個IF語句判定是不是X>Y,如果是,則此時pthread_cond_signal()函數會喚醒第一個線程 ,并在下一句中釋放互斥量mut。然后第一個線程開始從pthread_cond_wait()執行,首先要再次鎖mut, 如果鎖成功,再進行條件的判斷 (至于為什么用WHILE,即在被喚醒之后還要再判斷,后面有原因分析),如果滿足條件,則被喚醒進行處理,最后釋放互斥量mut

??? 至于為什么在被喚醒之后還要再次進行條件判斷(即為什么要使用while循環來判斷條件),是因為可能有“驚群效應”。有人覺得此處既然是被喚醒的,肯定是滿足條件了,其實不然。如果是多個線程都在等待這個條件,而同時只能有一個線程進行處理,此時就必須要再次條件判斷,以使只有一個線程進入臨界區處理。對此,轉來一段:

引用下POSIX的RATIONALE:

Condition Wait Semantics

It is important to note that when pthread_cond_wait() and pthread_cond_timedwait() return without error, the associated predicate may still be false. Similarly, when pthread_cond_timedwait() returns with the timeout error, the associated predicate may be true due to an unavoidable race between the expiration of the timeout and the predicate state change.

The application needs to recheck the predicate on any return because it cannot be sure there is another thread waiting on the thread to handle the signal, and if there is not then the signal is lost. The burden is on the application to check the predicate.

Some implementations, particularly on a multi-processor, may sometimes cause multiple threads to wake up when the condition variable is signaled simultaneously on different processors.

In general, whenever a condition wait returns, the thread has to re-evaluate the predicate associated with the condition wait to determine whether it can safely proceed, should wait again, or should declare a timeout. A return from the wait does not imply that the associated predicate is either true or false.

It is thus recommended that a condition wait be enclosed in the equivalent of a "while loop" that checks the predicate.

從上文可以看出:
1,pthread_cond_signal在多處理器上可能同時喚醒多個線程,當你只能讓一個線程處理某個任務時,其它被喚醒的線程就需要繼續 wait,while循環的意義就體現在這里了,而且規范要求pthread_cond_signal至少喚醒一個pthread_cond_wait上的線程,其實有些實現為了簡單在單處理器上也會喚醒多個線程.
2,某些應用,如線程池,pthread_cond_broadcast喚醒全部線程,但我們通常只需要一部分線程去做執行任務,所以其它的線程需要繼續wait.所以強烈推薦此處使用while循環.

?????? 其實說白了很簡單,就是pthread_cond_signal()也可能喚醒多個線程,而如果你同時只允許一個線程訪問的話,就必須要使用while來進行條件判斷,以保證臨界區內只有一個線程在處理。

?

?

?

淺析pthread_cond_wait



條件變量是利用線程間共享的全局變量進行同步的一種機制,主要包括兩個動作:一個線程等待"條件變量的條件成立"而掛起;另一個線程使"條件成立"(給出條件成立信號)。為了防止競爭,條件變量的使用總是和一個互斥鎖結合在一起。

一 pthread_cond_wait定義:

函數原型:int?? pthread_cond_wait(pthread_cond_t?? *cond,?? pthread_mutex_t?? *mutex)??

參數: cond 條件變量? mutex 互斥鎖
第一個參數*cond是指向一個條件變量的指針。第二個參數*mutex則是對相關的互斥鎖的指針。

二 pthread_cond_wait示例理解

pthread_cond_wait的機制比較難里理解,是條件變量中重要的成分。條件變量用于線程間同步,那么pthread_cond_wait必須和互斥鎖同時作用在一個線程里,它同時起到對資源的加鎖和解鎖,看下面的示例:


程序創建了2個新線程使他們同步運行,實現進程t_b打印9以內3的倍數,t_a打印其他的數,程序開始線程t_b不滿足條件等待,線程t_a運行使a循環加1并打印。直到i為3的倍數時,線程t_a發送信號通知進程t_b,這時t_b滿足條件,打印i值。

C++代碼 復制代碼?收藏代碼
  1. 1?#include<pthread.h> ??
  2. ??2?#include<unistd.h> ??
  3. ??3?#include<stdio.h> ??
  4. ??4?#include<stdlib.h> ??
  5. ??5? ??
  6. ??6?pthread_mutex_t?mutex?=?PTHREAD_MUTEX_INITIALIZER;/*初始化互斥鎖*/??
  7. ??7?pthread_cond_t??cond?=?PTHREAD_COND_INITIALIZER;//init?cond??
  8. ??8? ??
  9. ??9?void?*thread1(void*); ??
  10. ?10?void?*thread2(void*); ??
  11. ?11? ??
  12. ?12?int?i?=?1;?//global??
  13. ?13? ??
  14. ?14?int?main(void){ ??
  15. ?15?????pthread_t?t_a; ??
  16. ?16?????pthread_t?t_b;//two?thread ??
  17. ?17? ??
  18. ?18?????pthread_create(&t_a,NULL,thread2,(void*)NULL); ??
  19. ?19?????pthread_create(&t_b,NULL,thread1,(void*)NULL);//Create?thread??
  20. ?20? ??
  21. ?21?????pthread_join(t_b,NULL);//wait?a_b?thread?end??
  22. ?22?????pthread_mutex_destroy(&mutex); ??
  23. ?23?????pthread_cond_destroy(&cond); ??
  24. 24?????exit(0); ??
  25. ?25?} ??
  26. ?26? ??
  27. ?27?void?*thread1(void?*junk){ ??
  28. ?28?????for(i?=?1;i<=?9;?i++){ ??
  29. ?29?????????pthread_mutex_lock(&mutex);?//互斥鎖??
  30. ?30?????????printf("call?thread1?\n"); ??
  31. ?31?????????if(i%3?==?0) ??
  32. ?32?????????????pthread_cond_signal(&cond);?//send?sianal?to?t_b??
  33. ?33?????????else??
  34. ?34?????????????printf("thread1:?%d\n",i); ??
  35. ?35?????????pthread_mutex_unlock(&mutex); ??
  36. ?36?????????sleep(1); ??
  37. ?37?????} ??
  38. ?38?} ??
  39. ?39? ??
  40. ?40?void?*thread2(void*junk){ ??
  41. ?41?????while(i?<?9) ??
  42. ?42?????{ ??
  43. ?43?????????pthread_mutex_lock(&mutex); ??
  44. ?44?????????printf("call?thread2?\n"); ??
  45. ?45?????????if(i%3?!=?0) ??
  46. ?46?????????????pthread_cond_wait(&cond,&mutex);?//wait??
  47. ??47?????????printf("thread2:?%d\n",i); ??
  48. ?48?????????pthread_mutex_unlock(&mutex); ??
  49. ?49?????????sleep(1); ??
  50. ?50?????} ??
  51. ?51?}??????????????????????????????????????


輸出:
call thread2
call thread1
thread1: 1
call thread1
thread1: 2
call thread1
thread2: 3
call thread1
thread1: 4
call thread2
call thread1
thread1: 5
call thread1
thread2: 6
call thread1
thread1: 7
call thread2
call thread1
thread1: 8
call thread1
thread2: 9

示例的解釋:
call thread2:是線程2即t_b首先上鎖,即 pthread_mutex_lock(&mutex);鎖住了mutex使得此進程執行線程2中的臨界區的代碼,當執行到45行:if(i%3 != 0),此時i=1,滿足此條件,則執行46行: pthread_cond_wait(&cond,&mutex); 這句是關鍵,pthread_cond_wait(&cond,&mutex)操作有兩步,是原子操作:第一 解鎖,先解除之前的pthread_mutex_lock鎖定的mutex;第二 掛起,阻塞并在等待對列里休眠,即線程2掛起,直到再次被喚醒,喚醒的條件是由pthread_cond_signal(&cond);發出的cond信號來喚醒。

call thread1:由于pthread_cond_wait已經對線程2解鎖,此時另外的線程只有線程1,那么線程1對mutex上鎖,若這時有多個線程,那么線程間上鎖的順序和操作系統有關。

thread1: 1:線程1上鎖后執行臨界區的代碼,當執行到if(i%3 == 0)此時i=1,不滿足條件,則pthread_cond_signal(&cond);不被執行,那么線程2仍處于掛起狀態,輸出thread1: 1后線程1由pthread_mutex_unlock(&mutex);解鎖。

thread1: 2:這時此進程中只有2個線程,線程2處于掛起狀態,那么只有線程1,則線程1又對mutex上鎖,此時同樣執行臨界區的代碼,而且i=2,不滿足條件,pthread_cond_signal(&cond);不被執行,那么線程2仍處于掛起狀態,輸出thread1: 1后線程1由pthread_mutex_unlock(&mutex);解鎖。

call thread1:同樣由線程1上鎖,但此時i=3,滿足條件pthread_cond_signal(&cond)被執行,那么pthread_cond_signal(&cond)會發出信號,來喚醒處于掛起的線程2。pthread_cond_signal同樣由兩個原子操作:1,解鎖;2,發送信號;解鎖即對線程1解鎖,解除對mutex的上鎖。發送信號,即給等待signal掛起的線程2發送信號,喚醒掛起的線程2。

thread2: 3:由于pthread_cond_signal喚醒了線程2,即i=3滿足條件,pthread_cond_wait(&cond,&mutex);被執行,那么pthread_cond_wait(&cond,&mutex)此時也有一步操作:上鎖;即對線程2上鎖,此時的pthread_cond_wait(&cond,&mutex)的操作相當與pthread_mutex_lock(&mutex);那么線程2繼續執行上鎖后的臨界區的代碼,并由pthread_mutex_unlock(&mutex);對線程2進行解鎖。

剩下的輸出原理和上面解釋的一樣。


縱觀pthread_cond_wait,它的理解不可之把它看作一個簡單的wait函數,它里面應該是一族函數,不同的函數在不同的條件下執行,理解pthread_cond_wait的機制可以很好的學習條件變量

?

假如條件變量上有多個線程在等待,pthread_cond_broadcast會喚醒所有的等待線程,而pthread_cond_signal只會喚醒其中一個等待線程

一、什么是條件變量

?????? 與互斥鎖不同,條件變量是用來等待而不是用來上鎖的。條件變量用來自動阻塞一個線程,直到某特殊情況發生為止。通常條件變量和互斥鎖同時使用。

?????? 條件變量使我們可以睡眠等待某種條件出現。條件變量是利用線程間共享的全局變量進行同步的一種機制,主要包括兩個動作:一個線程等待"條件變量的條件成立"而掛起;另一個線程使"條件成立"(給出條件成立信號)。

條件的檢測是在互斥鎖的保護下進行的。如果一個條件為假,一個線程自動阻塞,并釋放等待狀態改變的互斥鎖。如果另一個線程改變了條件,它發信號給關聯的條件變量,喚醒一個或多個等待它的線程,重新獲得互斥鎖,重新評價條件。如果兩進程共享可讀寫的內存,條件變量可以被用來實現這兩進程間的線程同步。

?????? 使用條件變量之前要先進行初始化。可以在單個語句中生成和初始化一個條件變量如:

pthread_cond_t my_condition=PTHREAD_COND_INITIALIZER;(用于進程間線程的通信)。

也可以利用函數pthread_cond_init動態初始化。

?

二、條件變量函數

1

名稱:

pthread_cond_init

目標:

條件變量初始化

頭文件:

#include < pthread.h>

函數原形:

int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);

參數:

cptr? 條件變量

attr? 條件變量屬性

返回值:

成功返回0,出錯返回錯誤編號。

?????

?

?

?

?

?

?

?

?

?

pthread_cond_init函數可以用來初始化一個條件變量。他使用變量attr所指定的屬性來初始化一個條件變量,如果參數attr為空,那么它將使用缺省的屬性來設置所指定的條件變量。

?

2.

名稱:

pthread_cond_destroy

目標:

條件變量摧毀

頭文件:

#include < pthread.h>

函數原形:

int pthread_cond_destroy(pthread_cond_t *cond);

參數:

cptr? 條件變量

返回值:

成功返回0,出錯返回錯誤編號。

??????

?

?

?

?

?

?

?

pthread_cond_destroy函數可以用來摧毀所指定的條件變量,同時將會釋放所給它分配的資源。調用該函數的進程也并不要求等待在參數所指定的條件變量上。

?

3.

名稱:

pthread_cond_wait/pthread_cond_timedwait

目標:

條件變量等待

頭文件:

#include < pthread.h>

函數原形:

int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);

int pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t mytex,const struct timespec *abstime);

參數:

cond 條件變量

mutex 互斥鎖

返回值:

成功返回0,出錯返回錯誤編號。

??????

?

?

?

?

?

?

?

?

?

?

第一個參數*cond是指向一個條件變量的指針。第二個參數*mutex則是對相關的互斥鎖的指針。函數pthread_cond_timedwait函數類型與函數pthread_cond_wait,區別在于,如果達到或是超過所引用的參數*abstime,它將結束并返回錯誤ETIME.pthread_cond_timedwait函數的參數*abstime指向一個timespec結構。該結構如下:

typedef struct timespec{

?????? time_t tv_sec;

?????? long tv_nsex;

}timespec_t;

?

3.

名稱:

pthread_cond_signal/pthread_cond_broadcast

目標:

條件變量通知

頭文件:

#include < pthread.h>

函數原形:

int pthread_cond_signal(pthread_cond_t *cond);

int pthread_cond_broadcast(pthread_cond_t *cond);

參數:

cond 條件變量

返回值:

成功返回0,出錯返回錯誤編號。

??????

?

?

?

?

?

?

?

?

參數*cond是對類型為pthread_cond_t 的一個條件變量的指針。當調用pthread_cond_signal時一個在相同條件變量上阻塞的線程將被解鎖。如果同時有多個線程阻塞,則由調度策略確定接收通知的線程。如果調用pthread_cond_broadcast,則將通知阻塞在這個條件變量上的所有線程。一旦被喚醒,線程仍然會要求互斥鎖。如果當前沒有線程等待通知,則上面兩種調用實際上成為一個空操作。如果參數*cond指向非法地址,則返回值EINVAL

?

下面是一個簡單的例子,我們可以從程序的運行來了解條件變量的作用。

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*
初始化互斥鎖*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*
初始化條件變量*/

void *thread1(void *);
void *thread2(void *);

int i=1;
int main(void)
{
??? pthread_t t_a;
??? pthread_t t_b;

??? pthread_create(&t_a,NULL,thread2,(void *)NULL);/*
創建進程t_a*/
??? pthread_create(&t_b,NULL,thread1,(void *)NULL); /*
創建進程t_b*/
??? pthread_join(t_b, NULL);/*
等待進程t_b結束*/
??? pthread_mutex_destroy(&mutex);
??? pthread_cond_destroy(&cond);
??? exit(0);
}

void *thread1(void *junk)
{
??? for(i=1;i<=9;i++)
??? {
? ? ????pthread_mutex_lock(&mutex);/*
鎖住互斥量*/
? ? ????if(i%3==0)
? ?? ??????? pthread_cond_signal(&cond);/*
條件改變,發送信號,通知t_b進程*/
? ? ????else? ? ? ?
? ?? ??????? printf("thead1:%d\n",i);
? ? ????pthread_mutex_unlock(&mutex);/*
解鎖互斥量*/

sleep(1);
}

}

void *thread2(void *junk)
{
??? while(i<9)
??? {
? ? ????pthread_mutex_lock(&mutex);

if(i%3!=0)
? ? ????????pthread_cond_wait(&cond,&mutex);/*
等待*/
? ? ????printf("thread2:%d\n",i);
? ? ????pthread_mutex_unlock(&mutex);

sleep(1);
}

}

程序創建了2個新線程使他們同步運行,實現進程t_b打印20以內3的倍數,t_a打印其他的數,程序開始線程t_b不滿足條件等待,線程t_a運行使a循環加1并打印。直到i3的倍數時,線程t_a發送信號通知進程t_b,這時t_b滿足條件,打印i值。

下面是運行結果:

#cc –lpthread –o cond cond.c

#./cond

thread1:1

thread1:2

thread2:3

thread1:4

thread1:5

thread2:6

thread1:7

thread1:8

thread2:9


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/253564.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/253564.shtml
英文地址,請注明出處:http://en.pswp.cn/news/253564.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

HDU 1525 Euclid's Game

題目大意&#xff1a; 題目給出了兩個正數a.b 每次操作&#xff0c;大的數減掉小的數的整數倍。一個數變為0 的時候結束。 誰先先把其中一個數減為0的獲勝。問誰可以贏。Stan是先手。 題目思路&#xff1a; 無論a,b的值為多少&#xff0c;局面&#xff1a;[a%b&#xff0c;b] 一…

SRAM BIST技術學習

MBIST 方法是目前大容量存儲器測試的主流技術&#xff0c;該技術利用芯片內部專門設計的BIST 電路進行自動化測試&#xff0c;能夠對嵌入式存儲器這種具有復雜電路結構的嵌入式模塊進行全面的測試。MBIST 電路將產生測試向量的電路模塊以及檢測測試結果的比較模塊都置于芯片的內…

【Zigbee技術入門教程-02】一圖讀懂ZStack協議棧的核心思想與工作機理

【Zigbee技術入門教程-02】一圖讀懂ZStack協議棧的核心思想與工作機理 廣東職業技術學院 歐浩源 Z-Stack協議棧是一個基于任務輪詢方式的操作系統&#xff0c;其任務調度和資源分配由操作系統抽象層OSAL管理著。 你可以理解為&#xff1a;Z-Stack協議棧 OSAL操作系統 CC25…

CMOS圖像傳感器——SmartSens

近年來CIS發展成為增量市場,國產CIS廠商也踴躍布局,給業界帶來許多驚喜。思特威(上海)電子科技股份有限公司(SmartSens)正是國產CIS中亮眼的一家廠商。數據顯示,2020年思特威安防監控市場的CIS芯片出貨量為1.46億顆,繼續位居全球出貨量TOP1的位置;同年,思特威的新興領…

Servlet第二篇【Servlet調用圖、Servlet細節、ServletConfig、ServletContext】

Servlet的調用圖 前面我們已經學過了Servlet的生命周期了&#xff0c;我們根據Servlet的生命周期畫出Servlet的調用圖加深理解 Servlet的細節 一個已經注冊的Servlet可以被多次映射 同一個Servlet可以被映射到多個URL上。 <servlet><servlet-name>Demo1</servle…

vue響應式原理

vue響應式原理 initState new Vue() > _init() > initState: function initState (vm: Component) {vm._watchers []const opts vm.$optionsif (opts.props) initProps(vm, opts.props)if (opts.methods) initMethods(vm, opts.methods)if (opts.data) {initData(vm)} …

Oracle數據庫管理與開發pdf

下載地址&#xff1a;網盤下載基本介紹編輯內容簡介Oracle是一個適合于大中型企事業的數據庫管理系統&#xff0c;在銀行、電信、移動通信、航空、保險、金融、氣象、鐵路、跨國公司和電子商務等諸多領域得到了廣泛的應用。據統計&#xff0c;在所有數據庫管理系統中&#xff0…

DVS/DVR區別

一、DVS &#xff08;Digital Video Server&#xff09;網絡視頻服務器的簡稱。DVS(網絡視頻服務器)的原理網絡視頻服務器主要實現模擬視音頻信號的IP 化。經數字化的視音頻信號MPEG-4 視頻壓縮算法和G.729/ADPCM 音頻壓縮算法進行壓縮編碼&#xff0c;然后通過IP 網將低碼率的…

自動對焦方法學習

實現自動對焦的方法有很多種,可以根據不同的工作原理,將自動對焦技術分成不同種類。 按照系統是否自帶信號發射系統,可以分為主動式與被動式兩種類型。 主動式對焦方法是由成像系統中的發射裝置發出信號,然后再由接收裝置接收從被攝景物所反射回來的反饋信號并利用通過計算…

微粒化運營:升級內容產業消費體驗(附視頻版)

那些最受歡迎的內容平臺做對了什么&#xff1f; Facebook和Google是全球互聯網廣告產業中最早開始微粒化運營的代表&#xff0c;Google的互聯網精準廣告的思路與微粒化運營是完全相同的&#xff0c;這兩家公司也因此獲得了全球超過20%的互聯網廣告的收入。 以Facebook為例&…

mycat讀寫分離

只需要讀寫分離的功能&#xff0c;分庫分表的都不需要。 涉及到的配置文件&#xff1a; 1.conf/server.xml 主要配置的是mycat的用戶名和密碼&#xff0c;mycat的用戶名和密碼和mysql的用戶名密碼是分開的&#xff0c;應用連接mycat就用這個用戶名和密碼。 <?xml version&q…

chisel快速入門(一)

一、概述 Chisel&#xff08;Constructing Hardware In a Scala Embedded Language&#xff09;是一種嵌入在高級編程語言Scala的硬件構建語言。Chisel實際上只是一些特殊的類定義&#xff0c;預定義對象的集合&#xff0c;使用Scala的用法&#xff0c;所以在寫Chisel程序時實際…

DVS/DVR常見的監控名詞

英文名詞 說明BNC 全稱Bayonet Nut Connector&#xff0c;一種用于同軸電纜的連接器DHCP 動態主機配置協議&#xff0c;用于動態地指派配置信息DNS 域名系統&#xff0c;以用戶友好的方式將名字轉換為…

導出數據生成excel

前臺&#xff1a; <asp:Button ID"btnMoney" runat"server" Text"經費使用總結表" CssClass"admin_cx marginleft" Height"25" OnClick"btnMoney_Click" /> 后臺&#xff1a; protected void btnMoney_Cli…

U盤基本處理,U盤與移動固態硬盤

一、辨別 USB2.0 和 USB3.0 1、從USB外觀上來看&#xff0c;USB2.0通常是白色或黑色&#xff0c;而USB3.0則改觀為“高大上”的藍色接口。 目前&#xff0c;部分筆記本電腦USB接口&#xff0c;已同時提供對USB2.0及USB3.0的支持&#xff0c;我們可以通過接口顏色來區別。 2、從…

UWP_小說在線閱讀器:功能要求與技術要求

注&#xff1a;2017年2月23日正式提上日程 學了WP開發也有一年了&#xff0c;也沒做過什么軟件的。17年進發UWP&#xff0c;鍛煉自己一下。做一個開源的小說閱讀器吧。 既然開發一個軟件。所以要設計一下吧。 功能要求&#xff1a; 可能要用到的技術&#xff0c;這個嗎&#xf…

chisel快速入門(二)

上一篇見此&#xff1a; chisel快速入門&#xff08;一&#xff09;_滄海一升的博客-CSDN博客簡單介紹了chisel&#xff0c;使硬件開發者能快速上手chisel。https://blog.csdn.net/qq_21842097/article/details/121415341 十、運行和測試 現在我們已經定義了模塊&#xff0c;…

【WPF】設置TextBox內容為空時的提示文字

原文:【WPF】設置TextBox內容為空時的提示文字<TextBox Width"150" Margin"5"><TextBox.Resources><VisualBrush x:Key"HintText" TileMode"None" Opacity"0.5" Stretch"None" AlignmentX"Le…

視頻矩陣

視頻矩陣&#xff0c;就將視頻圖像從任意一個輸入通道切換到任意一個輸出通道顯示。一般來講,一個MN矩陣&#xff1a;表示它可以同時支持M路圖像輸入和N路圖像輸出。即任意的一個輸入和任意的一個輸出。 視頻矩陣 - 基本功能和要求 一個矩陣系統通常還應該包括以下基本功能&…

Spring 教程03

spring-3 1. Xml<!-- \src\applicationContext-xml.xml --> <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance…