日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁(yè) > > C語(yǔ)言與CPP編程
[導(dǎo)讀]C++11其實(shí)主要就四方面內(nèi)容,第一個(gè)是可變參數(shù)模板,第二個(gè)是右值引用,第三個(gè)是智能指針,第四個(gè)是內(nèi)存模型(Memory Model)。相對(duì)來(lái)說(shuō),這也是較難理解的幾個(gè)特性,分別針對(duì)于泛型編程,內(nèi)存優(yōu)化,內(nèi)存管理和并發(fā)編程。

C++11其實(shí)主要就四方面內(nèi)容,第一個(gè)是可變參數(shù)模板,第二個(gè)是右值引用,第三個(gè)是智能指針,第四個(gè)是內(nèi)存模型(Memory Model)。

相對(duì)來(lái)說(shuō),這也是較難理解的幾個(gè)特性,分別針對(duì)于泛型編程,內(nèi)存優(yōu)化,內(nèi)存管理和并發(fā)編程。

并發(fā)編程是個(gè)非常大的模塊,而在諸多內(nèi)容底下有一個(gè)基本的概念,就是并發(fā)內(nèi)存模型(Memory Model)。

那么,什么是內(nèi)存模型?

1
Memory Model

早在之前介紹并發(fā)編程的文章中,我們就知道同步共享數(shù)據(jù)很重要。而同步可分為兩種方式:原子操作和順序約束。

原子操作是數(shù)據(jù)操作的最小單元,天生不可再分;順序約束可以協(xié)調(diào)各個(gè)線程之間數(shù)據(jù)訪問(wèn)的先后順序,避免數(shù)據(jù)競(jìng)爭(zhēng)。

通常的同步方式會(huì)有兩個(gè)問(wèn)題,一是效率不夠,二是死鎖問(wèn)題。導(dǎo)致效率不夠是因?yàn)檫@些方式都是lock-based的。

當(dāng)然,若非非常在意效率,完全可以使用這些同步方式,因其簡(jiǎn)單方便且不易出錯(cuò)。

若要追求更高的效率,需要學(xué)習(xí)lock-free(無(wú)鎖)的同步方式。

內(nèi)存模型,簡(jiǎn)單地說(shuō),是一種介于開(kāi)發(fā)者和系統(tǒng)之間的并發(fā)約定,可以無(wú)鎖地保證程序的執(zhí)行邏輯與預(yù)期一致。

這里的系統(tǒng)包括編譯器、處理器和緩存,各部分都想在自己的領(lǐng)域?qū)Τ绦蜻M(jìn)行優(yōu)化,以提高性能,而這些優(yōu)化會(huì)打亂源碼中的執(zhí)行順序。尤其是在多線程上,這些優(yōu)化會(huì)對(duì)共享數(shù)據(jù)造成巨大影響,導(dǎo)致程序的執(zhí)行結(jié)果往往不遂人意。

內(nèi)存模型,就是來(lái)解決這些優(yōu)化所帶來(lái)的問(wèn)題。主要包含三個(gè)方面:

  • Atomic operations(原子操作)

  • Partial?ordering of operations(局部執(zhí)行順序)

  • Visible effects of operations(操作可見(jiàn)性)

原子操作和局部執(zhí)行順序如前所述,「操作可見(jiàn)性」指的是不同線程之間操作共享變量是可見(jiàn)的。

原子數(shù)據(jù)的同步是由編譯器來(lái)保證的,而非原子數(shù)據(jù)需要我們自己來(lái)規(guī)劃順序。

2

關(guān)系定義

這里有三種關(guān)系術(shù)語(yǔ),

  • sequenced-before

  • happens-before

  • synchronizes-with

同一線程語(yǔ)句之間,若A操作在B操作之前執(zhí)行,則表示為A sequenced-before B,A的執(zhí)行結(jié)果對(duì)B可見(jiàn)。
而在不同線程的語(yǔ)句之間,若A操作在B操作之前就已發(fā)生,則表示為A happens-before B。該關(guān)系具有可傳遞性,也就是說(shuō),若A happens-before B,B happens-before C,則一定能得出A happens-before C。
若A操作的狀態(tài)改變引發(fā)了B操作的執(zhí)行,則表示為A synchronizes-with B。比如我們學(xué)過(guò)的事件、條件變量、信號(hào)量等等都會(huì)因一個(gè)條件(狀態(tài))滿足,而執(zhí)行相應(yīng)的操作,這種狀態(tài)關(guān)系就叫做synchronizes-with。
由于synchronizes-with的特性,可以借其實(shí)現(xiàn)happens-before關(guān)系。
內(nèi)存模型就是提供一個(gè)操作的約束語(yǔ)義,借其可以滿足上述關(guān)系,實(shí)現(xiàn)了順序約束。

3

Atomics(原子操作)

原子操作的知識(shí)之前也介紹過(guò),限于篇幅,便不再捉細(xì)節(jié)。
先來(lái)整體看一下原子操作支持的操作類型,后面再來(lái)講應(yīng)用。
這里挑兩個(gè)來(lái)介紹一下相關(guān)操作,算是回顧。
第一個(gè)來(lái)講atomic_flag,這是最簡(jiǎn)單的原子類型,代表一個(gè)布爾標(biāo)志,可用它實(shí)現(xiàn)一個(gè)自旋鎖:

1#include?
2#include?
3#include?
4
5class?spin_lock
6{

7????std::atomic_flag?flag?=?ATOMIC_FLAG_INIT;
8public:
9????void?lock()?{?while(flag.test_and_set());?}
10
11????void?unlock()?{?flag.clear();?}
12};
13
14spin_lock?spin;
15int?g_num?=?0;
16void?work()
17
{
18????spin.lock();
19
20????g_num++;
21
22????spin.unlock();
23}
24
25int?main()
26
{
27????std::thread?t1(work);
28????std::thread?t2(work);
29????t1.join();
30????t2.join();
31
32????std::cout?<33
34????return?0;
35}

atomic_flag必須使用ATOMIC_FLAG_INIT初始化,該值就是0,也就是false。
只能通過(guò)兩個(gè)接口來(lái)操作atomic_flag:
  • clear:清除操作,將值設(shè)為false。

  • test_and_set:將值設(shè)為true并返回之前的值。


第9行的lock()函數(shù)實(shí)現(xiàn)了自旋鎖,當(dāng)?shù)谝粋€(gè)線程進(jìn)來(lái)的時(shí)候,由于atomic_flag為false,所以會(huì)通過(guò)test_and_set設(shè)置為true并返回false,第一個(gè)線程于是可以接著執(zhí)行下面的邏輯。

當(dāng)?shù)诙€(gè)線程進(jìn)來(lái)時(shí),flag為true,因此會(huì)一直循環(huán),只有第一個(gè)線程中unlock了才會(huì)接著執(zhí)行。由此保證了共享變量g_num。
第二個(gè)來(lái)講atomic,它所支持的原子操作要比atomic_flag多。
一個(gè)簡(jiǎn)單的同步操作:

1#include?
2#include?
3#include?
4#include?
5#include?
6#include?
7
8std::atomic<bool>?flag{false};
9std::vector<int>?shared_values;
10void?work()
11
{
12????std::cout?<"waiting"?<std::endl;
13????while(!flag.load())
14????{
15????????std::this_thread::sleep_for(std::chrono::milliseconds(5));
16????}
17
18????shared_values[1]?=?2;
19????std::cout?<"end?of?the?work"?<std::endl;
20}
21
22void?set_value()
23
{
24????shared_values?=?{?7,?8,?9?};
25????flag?=?true;
26????std::cout?<"data?prepared"?<std::endl;
27}
28
29int?main()
30
{
31????std::thread?t1(work);
32????std::thread?t2(set_value);
33????t1.join();
34????t2.join();
35
36????std::copy(shared_values.begin(),?shared_values.end(),?std::ostream_iterator<int>(std::cout,?"?"));
37
38????return?0;
39}

這里有兩個(gè)線程,它們之間擁有執(zhí)行順序,只有先在set_value函數(shù)中設(shè)置好共享值,才能在work函數(shù)中修改。
通過(guò)flag的load函數(shù)可以獲取原子值,在值未設(shè)置完成時(shí)其為false,所以會(huì)一直等待數(shù)據(jù)到來(lái)。當(dāng)flag變?yōu)閠rue時(shí),表示數(shù)據(jù)已經(jīng)設(shè)置完成,于是會(huì)繼續(xù)工作。

4

Memory ordering(內(nèi)存順序)

是什么保證了上述原子操作能夠在多線程環(huán)境下同步執(zhí)行呢?

其實(shí)在所有的原子操作函數(shù)中都有一個(gè)可選參數(shù)memory_order。比如atomic的load()和store()原型如下:

bool?std::_Atomic_bool::load(std::memory_order?_Order?=?std::memory_order_seq_cst)?const?noexcept
void?std::_Atomic_bool::store(bool?_Value,?std::memory_order?_Order?=?std::memory_order_seq_cst)?noexcept

這里的可選參數(shù)默認(rèn)為memory_order_seq_cst,所有的memory_order可選值為:

enum?memory_order?{

????memory_order_relaxed,
????memory_order_consume,
????memory_order_acquire,
????memory_order_release,
????memory_order_acq_rel,
????memory_order_seq_cst
};

這就是C++提供的如何實(shí)現(xiàn)順序約束的方式,通過(guò)指定特定的memory_order,可以實(shí)現(xiàn)前面提及的sequence-before、happens-before、synchronizes-with關(guān)系。

順序約束是我們和系統(tǒng)之間的一個(gè)約定,約定強(qiáng)度由強(qiáng)到弱可以分為三個(gè)層次:

  • Sequential consistency(順序一致性): memory_order_seq_cst
  • Acquire-release(獲取與釋放): memory_order_consume,memory_order_acquire,memory_order_release,memory_order_acq_rel
  • Relaxed(松散模型): memory_order_relaxed

Sequential consistency保證所有操作在線程之間都有一個(gè)全局的順序,Acquire-release保證在不同線程間對(duì)于相同的原子變量的寫(xiě)和讀的操作順序,Relaxed僅保證原子的修改順序。

為何要分層次呢?

其實(shí)順序約束和系統(tǒng)優(yōu)化之間是一種零和博弈,約束越強(qiáng),系統(tǒng)所能夠做的優(yōu)化便越少。

因此每個(gè)層次擁有效率差異,層次越低,優(yōu)化越多,效率也越高,不過(guò)掌握難度也越大。

所有的Memory order按照操作類型,又可分為三類:

  • Read(讀):memory_order_acquire,memory_order_consume

  • Write(寫(xiě)):memory_order_release

  • Read-modify-Write(讀-改-寫(xiě)):memory_order_acq_rel,memory_order_seq_cst

Relaxed未定義同步和順序約束,所以要單獨(dú)而論。

例如load()就是Read操作,store()就是Write()操作,compare_exchange_strong就是Read-modify-Write操作。

這意味著你不能將一個(gè)Read操作的順序約束,寫(xiě)到store()上。例如,若將memory_order_acquire寫(xiě)到store()上,不會(huì)產(chǎn)生任何效果。

我們先來(lái)從默認(rèn)的Sequential consistency開(kāi)始,往往無(wú)需設(shè)置,便默認(rèn)是memory_order_seq_cst,可以寫(xiě)一個(gè)簡(jiǎn)單的生產(chǎn)者-消費(fèi)者函數(shù):

1std::string?sc_value;
2std::atomic<bool>?ready{false};
3
4void?consumer()
5
{
6????while(!ready.load())?{}
7
8????std::cout?<std::endl;
9}
10
11void?producer()
12
{
13????sc_value?=?"produce?values";
14????ready?=?true;
15}
16
17int?main()
18
{
19????std::thread?t1(consumer);
20????std::thread?t2(producer);
21????t1.join();
22????t2.join();
23
24????return?0;
25}

此時(shí),執(zhí)行順序具有強(qiáng)保證性,一定是先執(zhí)行了producer再執(zhí)行的consumer。
用標(biāo)準(zhǔn)的關(guān)系術(shù)語(yǔ)來(lái)說(shuō)就是,第13行的操作和第14行的操作是sequenced-before關(guān)系,第14行和第6行的操作是synchronizes-with關(guān)系,進(jìn)而保證了14行的賦值操作一定在第6行的load()操作之前執(zhí)行,也就是保證了happens-before關(guān)系。
Acquire-release就開(kāi)始變得有些復(fù)雜,我們先以一個(gè)最簡(jiǎn)單的例子來(lái)看。

1class?spin_lock
2{

3????std::atomic_flag?flag?=?ATOMIC_FLAG_INIT;
4public:
5????spin_lock()?{}
6
7????void?lock()?{?while(flag.test_and_set(std::memory_order_acquire));?}
8
9????void?unlock()?{?flag.clear(std::memory_order_release);?}
10};
11
12spin_lock?spin;
13void?work()
14
{
15????spin.lock();
16????//?do?something
17????spin.unlock();
18}
19
20int?main()
21
{
22????std::thread?t1(work);
23????std::thread?t2(work);
24????t1.join();
25????t2.join();
26
27????return?0;
28}

clear()中使用了release,test_and_set()中使用了acquire,acquire和release操作之間是synchronizes-with的關(guān)系。

它的行為和之前使用sequential consistency默認(rèn)參數(shù)的自旋鎖一樣,不過(guò)要更加輕便高效。

test_and_set()操作其實(shí)是個(gè)Read-modify-Write操作,不過(guò)依舊可以使用acquire操作。release禁止了所有在它之前或之后的寫(xiě)操作亂序,acquire禁止了所有在它之前或之后的讀操作亂序。

在兩個(gè)不同的線程之間,共同訪問(wèn)同一個(gè)原子是flag,所添加的順序約束就是為了保證flag的修改順序。

我們?cè)賮?lái)看一個(gè)更清晰的例子:

1std::atomic<bool>?x{false},?y{false};
2std::atomic<int>?z{0};
3void?write()
4
{
5????//?relaxed只保證修改順序
6????x.store(true,?std::memory_order_relaxed);
7
8????//?release保證在它之前的所有寫(xiě)操作順序一致
9????y.store(true,?std::memory_order_release);
10}
11
12void?read()
13
{
14????//?acquire保證在它之前和之后的讀操作順序一致
15????while(!y.load(std::memory_order_acquire));
16
17????//?relaxed只保證修改順序
18????if(x.load(std::memory_order_relaxed))
19????????++z;
20}
21
22int?main()
23
{
24????std::thread?t1(write);
25????std::thread?t2(read);
26????t1.join();
27????t2.join();
28
29????assert(z.load()?!=?0);
30
31????return?0;
32}

注意這是使用了relaxed、release和acquire三種約束。
relaxed只保證修改順序,所以對(duì)于write()函數(shù)來(lái)說(shuō),一定是先執(zhí)行x后執(zhí)行y操作。不過(guò)若是將y也使用relaxed,雖然在write()中是先x后y的順序,而在read()的眼中,可能是先y后x的順序,這是優(yōu)化導(dǎo)致的。
而因?yàn)閥的讀和寫(xiě)使用了acquire和release約束,所以可以保證在不同線程間對(duì)于相同的原子變量讀和寫(xiě)的操作順序一致。
同時(shí),Acquire-release操作還擁有傳遞性,是典型的happens-before關(guān)系。
還是提供一個(gè)例子:

1std::vector<int>?shared_value;
2std::atomic<bool>?produced{false};
3std::atomic<bool>?consumed{false};
4
5void?producer()
6
{
7????shared_value?=?{?7,?8,?9?};
8
9????//?A.?realse happens-before B
10????produced.store(true,?std::memory_order_release);
11}
12
13void?delivery()
14
{
15????//?B.?acquire,A?synchronizes?with?B
16????while(!produced.load(std::memory_order_acquire));
17
18????//?B.?release happens-beforeC
19????consumed.store(true,?std::memory_order_release);
20}
21
22void?consumer()
23
{
24????//?C.?acquire,?B?synchronizes?with?C
25????//?therefore,?A?happens?before?C
26????while(!consumed.load(std::memory_order_acquire));
27
28????shared_value[1]?=?2;
29}
30
31int?main()
32
{
33????std::thread?t1(consumer);
34????std::thread?t2(producer);
35????std::thread?t3(delivery);
36????t1.join();
37????t2.join();
38????t3.join();
39
40????std::copy(shared_value.begin(),?shared_value.end(),?std::ostream_iterator<int>(std::cout,?"?"));
41
42????return?0;
43}

注釋已經(jīng)足夠說(shuō)明其中所以,便不細(xì)述。

5

Fences(柵欄)

看回先前的一個(gè)例子:

1std::atomic<bool>?x{false},?y{false};
2std::atomic<int>?z{0};
3void?write()
4
{
5????//?relaxed只保證修改順序
6????x.store(true,?std::memory_order_relaxed);
7????y.store(true,?std::memory_order_relaxed);
8}
9
10void?read()
11
{
12????//?relaxed只保證修改順序
13????while(!y.load(std::memory_order_relaxed));
14????if(x.load(std::memory_order_relaxed))
15????????++z;
16}


relaxed是最弱的內(nèi)存模型,此處全使用relaxed,順序?qū)⒉辉儆斜WC。

也許在read()中看到的write()操作是先y后x,那么此時(shí)read()里面的if操作便無(wú)法滿足,也就是說(shuō),++z不會(huì)被執(zhí)行。

解決方法是結(jié)合fences來(lái)使用,只需添加兩行代碼:

1std::atomic<bool>?x{false},?y{false};
2std::atomic<int>?z{0};
3void?write()
4
{
5????//?relaxed只保證修改順序
6????x.store(true,?std::memory_order_relaxed);
7
8????std::atomic_thread_fence(std::memory_order_release);
9
10????y.store(true,?std::memory_order_relaxed);
11}
12
13void?read()
14
{
15????//?relaxed只保證修改順序
16????while(!y.load(std::memory_order_relaxed));
17
18????std::atomic_thread_fence(std::memory_order_acquire);
19
20????if(x.load(std::memory_order_relaxed))
21????????++z;
22}

fences位于relaxed操作之間,它像一個(gè)柵欄一樣,可以保證前后的操作不會(huì)亂序。
具體細(xì)節(jié),接著來(lái)看。
C++提供了兩個(gè)類型的fences,
  • std::atomic_thread_fence:同步線程之間的內(nèi)存訪問(wèn)。

  • std::atomic_signal_fence:同步同一線程上的signal handler和code running。

我們主要學(xué)習(xí)第一個(gè)線程的fence,它會(huì)阻止特定的操作穿過(guò)柵欄,約束執(zhí)行順序。

有三種類型的fences,

  • Full fence:阻止兩個(gè)任意操作亂序。memory_order_seq_cst或memory_order_acq_rel。

  • Acquire fence:阻止讀操作亂序,memory_order_acquire。

  • Release fence:阻止寫(xiě)操作亂序,memory_order_release。

用圖來(lái)表示為:

圖中間灰色的一杠就表示fence,紅色表示禁止亂序,可以看到,除了Store-Load,其它操作都可以保障執(zhí)行順序。
同樣也有效率差異,可以針對(duì)具體的操作來(lái)選擇合適的fence。

6

總結(jié)

本篇內(nèi)容挺復(fù)雜的,其實(shí)就包含三個(gè)方面:Atomic operations(原子操作)、Partial?ordering of operations(局部執(zhí)行順序)和Visible effects of operations(操作可見(jiàn)性)。

面對(duì)一個(gè)復(fù)雜的概念,往往需要變換尺度來(lái)進(jìn)行理解,若一開(kāi)始便陷入諸多細(xì)節(jié)中去,難免迷失其中,看不到整體的結(jié)構(gòu)。
所以這里其實(shí)也就是以我自己的理解來(lái)寫(xiě),細(xì)節(jié)涉及不多,但整體結(jié)構(gòu)已算完整,想了解更多具體細(xì)節(jié)可以參考C++ Concurrency in Action

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢(shì)抑制與過(guò)流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問(wèn)題卻十分常見(jiàn),不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問(wèn)題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(chē)(EV)作為新能源汽車(chē)的重要代表,正逐漸成為全球汽車(chē)產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車(chē)的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車(chē)的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車(chē) 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車(chē)場(chǎng)照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢(shì)逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問(wèn)題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周?chē)娮釉O(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來(lái)解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開(kāi)關(guān)電源具有效率高的特性,而且開(kāi)關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開(kāi)關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉