Tasks
Core.Task — TypeGörev(func)Verilen func fonksiyonunu (argüman almayan bir çağrılabilir olmalıdır) yürütmek için bir Görev (yani coroutine) oluşturun. Görev, bu fonksiyon döndüğünde sona erer. Görev, schedule ile yapılandırıldığında, inşaat sırasında ebeveynin "dünya yaşı" içinde çalışacaktır.
!!! uyarı Varsayılan olarak görevlerin yapışkan bitinin t.sticky olarak ayarlandığına dikkat edin. Bu, @async için tarihsel varsayılanı modellemektedir. Yapışkan görevler yalnızca ilk olarak planlandıkları işçi iş parçacığında çalıştırılabilir ve planlandıklarında, planlandıkları görev yapışkan hale gelecektir. Threads.@spawn davranışını elde etmek için yapışkan bitini manuel olarak false olarak ayarlayın.
Örnekler
julia> a() = sum(i for i in 1:1000);
julia> b = Task(a);Bu örnekte, b henüz başlamamış bir çalıştırılabilir Görevdir.
Base.@task — Macro@taskBir ifadeyi çalıştırmadan Task içine sarın ve Task döndürün. Bu yalnızca bir görev oluşturur ve çalıştırmaz.
Varsayılan olarak görevlerin yapışkan bitinin true olarak ayarlanmış olacaktır t.sticky. Bu, @async için tarihsel varsayılanı modellemektedir. Yapışkan görevler yalnızca ilk olarak planlandıkları işçi iş parçacığında çalıştırılabilir ve planlandıklarında, planlandıkları görev yapışkan hale gelecektir. Threads.@spawn davranışını elde etmek için yapışkan bitini manuel olarak false olarak ayarlayın.
Örnekler
julia> a1() = sum(i for i in 1:1000);
julia> b = @task a1();
julia> istaskstarted(b)
false
julia> schedule(b);
julia> yield();
julia> istaskdone(b)
trueBase.@async — Macro@asyncBir ifadeyi Task içine sarın ve yerel makinenin zamanlayıcı kuyruğuna ekleyin.
Değerler, $ aracılığıyla @async içine interpolasyon yapılabilir; bu, değeri doğrudan oluşturulan alt kapanıma kopyalar. Bu, bir değişkenin değerini eklemenizi sağlar ve asenkron kodu mevcut görevdeki değişkenin değerindeki değişikliklerden izole eder.
@async yerine her zaman Threads.@spawn kullanmanız şiddetle tavsiye edilir paralellik gereksinimi olmasa bile, özellikle kamuya açık dağıtılan kütüphanelerde. Bunun nedeni, @async kullanımının, Julia'nın mevcut uygulamasında ebeveyn görevlerin işçi iş parçacıkları arasında taşınmasını devre dışı bırakmasıdır. Bu nedenle, bir kütüphane fonksiyonunda @async kullanımının görünüşte masum bir şekilde, kullanıcı uygulamalarının çok farklı bölümlerinin performansı üzerinde büyük bir etkisi olabilir.
$ aracılığıyla değerlerin interpolasyonu, Julia 1.4 itibarıyla mevcuttur.
Base.asyncmap — Functionasyncmap(f, c...; ntasks=0, batch_size=nothing)Bir koleksiyon (veya birden fazla eşit uzunlukta koleksiyon) üzerinde f'yi eşzamanlı görevler kullanarak haritalar. Birden fazla koleksiyon argümanı için, f eleman bazında uygulanır.
ntasks, eşzamanlı olarak çalıştırılacak görev sayısını belirtir. Koleksiyonların uzunluğuna bağlı olarak, ntasks belirtilmemişse, eşzamanlı haritalama için en fazla 100 görev kullanılacaktır.
ntasks, ayrıca sıfır argümanlı bir fonksiyon olarak da belirtilebilir. Bu durumda, her bir elemanı işlemden önce paralel olarak çalıştırılacak görev sayısı kontrol edilir ve ntasks_func değeri mevcut görev sayısından büyükse yeni bir görev başlatılır.
batch_size belirtilirse, koleksiyon toplu modda işlenir. Bu durumda, f, bir Vector argüman demetleri kabul eden ve bir sonuç vektörü döndüren bir fonksiyon olmalıdır. Girdi vektörünün uzunluğu batch_size veya daha az olacaktır.
Aşağıdaki örnekler, haritalama fonksiyonunun çalıştırıldığı görevlerin objectid'sini döndürerek farklı görevlerdeki yürütmeyi vurgular.
Öncelikle, ntasks tanımlanmamışken, her bir eleman farklı bir görevde işlenir.
julia> tskoid() = objectid(current_task());
julia> asyncmap(x->tskoid(), 1:5)
5-element Array{UInt64,1}:
0x6e15e66c75c75853
0x440f8819a1baa682
0x9fb3eeadd0c83985
0xebd3e35fe90d4050
0x29efc93edce2b961
julia> length(unique(asyncmap(x->tskoid(), 1:5)))
5ntasks=2 ile tüm elemanlar 2 görevde işlenir.
julia> asyncmap(x->tskoid(), 1:5; ntasks=2)
5-element Array{UInt64,1}:
0x027ab1680df7ae94
0xa23d2f80cd7cf157
0x027ab1680df7ae94
0xa23d2f80cd7cf157
0x027ab1680df7ae94
julia> length(unique(asyncmap(x->tskoid(), 1:5; ntasks=2)))
2batch_size tanımlandığında, haritalama fonksiyonu bir argüman demetleri dizisini kabul edecek ve bir sonuç dizisi döndürecek şekilde değiştirilmelidir. Bunu başarmak için değiştirilmiş haritalama fonksiyonunda map kullanılır.
julia> batch_func(input) = map(x->string("args_tuple: ", x, ", element_val: ", x[1], ", task: ", tskoid()), input)
batch_func (generic function with 1 method)
julia> asyncmap(batch_func, 1:5; ntasks=2, batch_size=2)
5-element Array{String,1}:
"args_tuple: (1,), element_val: 1, task: 9118321258196414413"
"args_tuple: (2,), element_val: 2, task: 4904288162898683522"
"args_tuple: (3,), element_val: 3, task: 9118321258196414413"
"args_tuple: (4,), element_val: 4, task: 4904288162898683522"
"args_tuple: (5,), element_val: 5, task: 9118321258196414413"Base.asyncmap! — Functionasyncmap!(f, results, c...; ntasks=0, batch_size=nothing)asyncmap gibi, ancak çıktıyı bir koleksiyon döndürmek yerine results içinde saklar.
!!! uyarı Herhangi bir değiştirilmiş argümanın başka bir argümanla bellek paylaşması durumunda davranış beklenmedik olabilir.
Base.current_task — Functioncurrent_task()Şu anda çalışan Task nesnesini alır.
Base.istaskdone — Functionistaskdone(t::Task) -> BoolBir görevin sona erip ermediğini belirleyin.
Örnekler
julia> a2() = sum(i for i in 1:1000);
julia> b = Task(a2);
julia> istaskdone(b)
false
julia> schedule(b);
julia> yield();
julia> istaskdone(b)
trueBase.istaskstarted — Functionistaskstarted(t::Task) -> BoolBir görevin çalışmaya başlayıp başlamadığını belirleyin.
Örnekler
julia> a3() = sum(i for i in 1:1000);
julia> b = Task(a3);
julia> istaskstarted(b)
falseBase.istaskfailed — Functionistaskfailed(t::Task) -> BoolBir görevin bir istisna atıldığı için çıkıp çıkmadığını belirleyin.
Örnekler
julia> a4() = error("görev başarısız");
julia> b = Task(a4);
julia> istaskfailed(b)
false
julia> schedule(b);
julia> yield();
julia> istaskfailed(b)
trueBu fonksiyon en az Julia 1.3 gerektirir.
Base.task_local_storage — Methodtask_local_storage(key)Mevcut görevin görev-yerel depolamasında bir anahtarın değerini kontrol edin.
Base.task_local_storage — Methodtask_local_storage(key, value)Mevcut görevin görev yerel depolamasında bir anahtara bir değer atar.
Base.task_local_storage — Methodtask_local_storage(body, key, value)value'ı key'e atayarak değiştirilmiş görev-yerel depolama ile body fonksiyonunu çağırır; key'in önceki değeri veya yokluğu daha sonra geri yüklenir. Dinamik kapsamı taklit etmek için yararlıdır.
Scheduling
Base.yield — Functionyield()Başka bir planlanmış görevin çalışmasına izin vermek için zamanlayıcıya geçin. Bu işlevi çağıran bir görev hala çalıştırılabilir durumdadır ve başka çalıştırılabilir görev yoksa hemen yeniden başlatılacaktır.
yield(t::Task, arg = nothing)schedule(t, arg); yield()'in hızlı, adaletsiz zamanlama versiyonu olan bu fonksiyon, zamanlayıcıyı çağırmadan önce hemen t'ye geçiş yapar.
Base.yieldto — Functionyieldto(t::Task, arg = nothing)Verilen göreve geçiş yapar. Bir göreve ilk kez geçildiğinde, görevin fonksiyonu hiçbir argüman olmadan çağrılır. Sonraki geçişlerde, arg son yieldto çağrısından döner. Bu, yalnızca görevleri değiştiren, durumları veya zamanlamayı dikkate almayan düşük seviyeli bir çağrıdır. Kullanımı önerilmez.
Base.sleep — Functionsleep(seconds)Mevcut görevi belirtilen sayıda saniye boyunca engeller. Minimum uyku süresi 1 milisaniye veya 0.001 girişi kadardır.
Base.schedule — Functionschedule(t::Task, [val]; error=false)Bir Task zamanlayıcının kuyruğuna eklenir. Bu, sistem başka bir şey yapmadığında görevin sürekli çalışmasını sağlar, ancak görev wait gibi bir engelleyici işlem yapıyorsa bu durum geçerli değildir.
İkinci bir argüman val sağlanırsa, bu değer görev tekrar çalıştığında (yieldto aracılığıyla) göreve iletilecektir. Eğer error true ise, değer uyanan görevde bir istisna olarak yükseltilir.
!!! uyarı Zaten başlatılmış bir Task üzerinde schedule kullanmak yanlıştır. Daha fazla bilgi için API referansına bakın.
!!! uyarı Varsayılan olarak görevlerin yapışkan bitinin true olarak ayarlandığı t.sticky olacaktır. Bu, @async için tarihsel varsayılanı modellemektedir. Yapışkan görevler yalnızca ilk olarak planlandıkları işçi iş parçacığında çalıştırılabilir ve planlandıklarında, planlandıkları görev yapışkan hale gelecektir. Threads.@spawn davranışını elde etmek için yapışkan bitini manuel olarak false olarak ayarlayın.
Örnekler
julia> a5() = sum(i for i in 1:1000);
julia> b = Task(a5);
julia> istaskstarted(b)
false
julia> schedule(b);
julia> yield();
julia> istaskstarted(b)
true
julia> istaskdone(b)
trueSynchronization
Base.errormonitor — Functionerrormonitor(t::Task)Görev t başarısız olursa stderr'ye bir hata günlüğü yazdırır.
Örnekler
julia> Base._wait(errormonitor(Threads.@spawn error("görev başarısız oldu")))
Unhandled Task ERROR: görev başarısız oldu
Stacktrace:
[...]Base.@sync — Macro@syncTüm sözdizimsel olarak kapsanan @async, @spawn, Distributed.@spawnat ve Distributed.@distributed kullanımlarının tamamlanmasını bekleyin. Kapsanan asenkron işlemler tarafından fırlatılan tüm istisnalar toplanır ve bir CompositeException olarak fırlatılır.
Örnekler
julia> Threads.nthreads()
4
julia> @sync begin
Threads.@spawn println("Thread-id $(Threads.threadid()), task 1")
Threads.@spawn println("Thread-id $(Threads.threadid()), task 2")
end;
Thread-id 3, task 1
Thread-id 1, task 2Base.wait — FunctionThreads.Condition için özel not:
Çağrıcı, bu yöntemi çağırmadan önce bir Threads.Condition'a sahip olan lock tutmalıdır. Çağrılan görev, genellikle aynı Threads.Condition nesnesi üzerinde notify çağrılarak başka bir görev tarafından uyandırılana kadar engellenecektir. Engelleme sırasında kilit atomik olarak serbest bırakılacak (kendi kendine kilitlenmiş olsa bile) ve geri dönerken yeniden edinilecektir.
wait(r::Future)Belirtilen Future için bir değerin mevcut olmasını bekleyin.
wait(r::RemoteChannel, args...)Belirtilen RemoteChannel üzerinde bir değerin kullanılabilir hale gelmesini bekleyin.
wait([x])Mevcut görevi, argümanın türüne bağlı olarak bir olay meydana gelene kadar engeller:
Channel: Kanalda bir değerin eklenmesini bekleyin.Condition: Bir koşuldanotifyiçin bekleyin venotify'ye geçirilenvalparametresini döndürün. Bir koşulda beklemek, ayrıcafirst=truegeçişine izin verir; bu, bekleyeninnotifyüzerinde uyanmak için sıranın ilk sırasına yerleştirilmesiyle sonuçlanır, bu da genellikle ilk giren ilk çıkar davranışıdır.Process: Bir işlemin veya işlem zincirinin çıkmasını bekleyin. Bir işleminexitcodealanı, başarı veya başarısızlığı belirlemek için kullanılabilir.Task: BirTask'ın bitmesini bekleyin. Eğer görev bir istisna ile başarısız olursa, birTaskFailedException(başarısız olan görevi saran) fırlatılır.RawFD: Bir dosya tanımlayıcısındaki değişiklikleri bekleyin (bkz.FileWatchingpaketi).
Hiçbir argüman geçilmezse, görev belirsiz bir süre engellenir. Bir görev yalnızca schedule veya yieldto için açık bir çağrı ile yeniden başlatılabilir.
Genellikle wait, beklenen bir koşulun karşılandığından emin olmak için bir while döngüsü içinde çağrılır.
wait(c::Channel)Channel isready olana kadar engeller.
julia> c = Channel(1);
julia> isready(c)
false
julia> task = Task(() -> wait(c));
julia> schedule(task);
julia> istaskdone(task) # görev engellendi çünkü kanal hazır değil
false
julia> put!(c, 1);
julia> istaskdone(task) # görev şimdi engellenmedi
trueBase.fetch — Methodfetch(t::Task)Bir Task tamamlanmasını bekleyin, ardından sonuç değerini döndürün. Görev bir istisna ile başarısız olursa, başarısız görevi saran bir TaskFailedException fırlatılır.
Base.fetch — Methodfetch(x::Any)x değerini döndür.
Base.timedwait — Functiontimedwait(testcb, timeout::Gerçek; pollint::Gerçek=0.1)testcb() true döndürene kadar veya timeout saniye geçene kadar bekleyin, hangisi daha önce olursa. Test fonksiyonu her pollint saniyede bir kontrol edilir. pollint için minimum değer 0.001 saniyedir, yani 1 milisaniye.
:ok veya :timed_out döndürün.
Örnekler
julia> cb() = (sleep(5); return);
julia> t = @async cb();
julia> timedwait(()->istaskdone(t), 1)
:timed_out
julia> timedwait(()->istaskdone(t), 6.5)
:okBase.Condition — TypeCondition()Görevlerin bekleyebileceği bir kenar tetiklemeli olay kaynağı oluşturur. Condition üzerinde wait çağrısı yapan görevler askıya alınır ve sıraya alınır. Daha sonra Condition üzerinde notify çağrısı yapıldığında görevler uyandırılır. Bir koşulda beklemek, bir değer döndürebilir veya notify 'nin isteğe bağlı argümanları kullanıldığında bir hata oluşturabilir. Kenar tetikleme, yalnızca notify çağrıldığında bekleyen görevlerin uyandırılabileceği anlamına gelir. Seviye tetiklemeli bildirimler için, bir bildirimin olup olmadığını takip etmek için ekstra bir durum tutmalısınız. Channel ve Threads.Event türleri bunu yapar ve seviye tetiklemeli olaylar için kullanılabilir.
Bu nesne THREAD-GÜVENLİ değildir. Thread-güvenli bir versiyon için Threads.Condition 'e bakın.
Base.Threads.Condition — TypeThreads.Condition([lock])Base.Condition için thread güvenli bir versiyon.
Bir Threads.Condition üzerinde wait veya notify çağırmak için önce ona lock çağırmalısınız. wait çağrıldığında, kilit atomik olarak bloklama sırasında serbest bırakılır ve wait döndüğünde yeniden edinilecektir. Bu nedenle, bir Threads.Condition c kullanımı aşağıdaki gibi görünmelidir:
lock(c)
try
while !thing_we_are_waiting_for
wait(c)
end
finally
unlock(c)
endBu işlevsellik en az Julia 1.2'yi gerektirir.
Base.Event — TypeEvent([autoreset=false])Seviye tetikleyici bir olay kaynağı oluşturur. wait çağrısı yapan görevler, Event üzerinde notify çağrısı yapılana kadar askıya alınır ve sıraya alınır. notify çağrısı yapıldıktan sonra, Event bir sinyal durumunda kalır ve görevler artık beklerken engellenmez, ta ki reset çağrısı yapılana kadar.
Eğer autoreset doğruysa, her notify çağrısı için en fazla bir görev wait'ten serbest bırakılacaktır.
Bu, notify/wait üzerinde bir edinme ve serbest bırakma bellek sıralaması sağlar.
Bu işlevsellik en az Julia 1.1 gerektirir.
autoreset işlevselliği ve bellek sıralama garantisi en az Julia 1.8 gerektirir.
Base.notify — Functionnotify(condition, val=nothing; all=true, error=false)Bir koşulu bekleyen görevleri uyandırın, onlara val geçirin. Eğer all true ise (varsayılan), bekleyen tüm görevler uyandırılır, aksi takdirde yalnızca biri uyandırılır. Eğer error true ise, geçirilen değer uyandırılan görevlerde bir istisna olarak yükseltilir.
Uyandırılan görevlerin sayısını döndürün. Eğer condition üzerinde bekleyen görev yoksa 0 döndürün.
Base.reset — Methodreset(::Event)Bir Event nesnesini ayarlanmamış bir duruma geri döndürür. Daha sonra wait çağrıları, notify tekrar çağrılana kadar engellenecektir.
Base.Semaphore — TypeSemaphore(sem_size)En fazla sem_size edinimin kullanılmasına izin veren bir sayım semaforu oluşturur. Her edinim, bir serbest bırakma ile eşleşmelidir.
Bu, edinim/serbest bırakma çağrıları üzerinde bir edinim ve serbest bırakma bellek sıralaması sağlar.
Base.acquire — Functionacquire(s::Semaphore)Bir sem_size izninin mevcut olmasını bekleyin, birinin alınmasını engelleyerek bekleyin.
acquire(f, s::Semaphore)Semaphore s'den alım yaptıktan sonra f'yi çalıştırır ve tamamlandığında veya hata oluştuğunda release eder.
Örneğin, aynı anda yalnızca 2 foo çağrısının aktif olmasını sağlayan bir do-block biçimi:
s = Base.Semaphore(2)
@sync for _ in 1:100
Threads.@spawn begin
Base.acquire(s) do
foo()
end
end
endBu yöntem en az Julia 1.8 gerektirir.
Base.release — Functionrelease(s::Semaphore)Havuzdan bir izin geri verin, bu da başka bir görevin onu almasına ve yürütmeye devam etmesine olanak tanıyabilir.
Base.AbstractLock — TypeAbstractLockSenkranma ilkelilerini uygulayan türleri tanımlayan soyut süper tür: lock, trylock, unlock ve islocked.
Base.lock — Functionlock(lock)lock mevcut olduğunda onu edin. Eğer lock başka bir görev/işlem tarafından zaten kilitlenmişse, mevcut hale gelmesini bekleyin.
Her lock, bir unlock ile eşleşmelidir.
lock(f::Function, lock)lock'ı al, lock tutulurken f'yi çalıştır ve f döndüğünde lock'ı serbest bırak. Eğer lock başka bir görev/iş parçacığı tarafından zaten kilitlenmişse, kullanılabilir hale gelene kadar bekle.
Bu fonksiyon döndüğünde, lock serbest bırakılmıştır, bu yüzden çağıran kişi unlock yapmaya çalışmamalıdır.
Ayrıca bakınız: @lock.
İkinci argüman olarak bir Channel kullanmak, Julia 1.7 veya daha yenisini gerektirir.
lock(f::Function, l::Lockable)
l ile ilişkili kilidi al, f'yi kilitli olarak çalıştır ve f döndüğünde kilidi serbest bırak. f, l tarafından sarılmış olan değeri alan bir konumsal argüman alacaktır. Eğer kilit başka bir görev/işlem tarafından zaten kilitlenmişse, kullanılabilir hale gelene kadar bekle. Bu fonksiyon döndüğünde, lock serbest bırakılmıştır, bu nedenle çağıran kişi onu unlock etmeye çalışmamalıdır.
En az Julia 1.11 gerektirir.
Base.unlock — Functionunlock(lock)lock'ın sahipliğini serbest bırakır.
Eğer bu daha önce edinilmiş bir rekürsif kilit ise, dahili bir sayacı azaltır ve hemen döner.
Base.trylock — Functiontrylock(lock) -> Başarı (Boolean)Kilidi mevcutsa alır ve başarılıysa true döner. Eğer kilit başka bir görev/iş parçacığı tarafından zaten kilitlenmişse, false döner.
Her başarılı trylock, bir unlock ile eşleşmelidir.
trylock fonksiyonu, islocked ile birleştirildiğinde, eğer typeof(lock) tarafından destekleniyorsa test-et-test-et-ve-set veya üssel geri çekilme algoritmalarını yazmak için kullanılabilir (belgesini okuyun).
Base.islocked — Functionislocked(lock) -> Durum (Boolean)lock'ın herhangi bir görev/iş parçacığı tarafından tutulup tutulmadığını kontrol eder. Bu fonksiyon tek başına senkronizasyon için kullanılmamalıdır. Ancak, islocked ile trylock birleştirildiğinde, test-et-test-et-ve-set veya üssel geri çekilme algoritmalarını yazmak için kullanılabilir eğer typeof(lock) tarafından destekleniyorsa (belgelerini okuyun).
Genişletilmiş yardım
Örneğin, lock uygulaması aşağıda belgelenen özellikleri karşıladıysa, üssel geri çekilme şu şekilde uygulanabilir.
nspins = 0
while true
while islocked(lock)
GC.safepoint()
nspins += 1
nspins > LIMIT && error("timeout")
end
trylock(lock) && break
backoff()
endUygulama
Bir kilit uygulamasının islocked'ı aşağıdaki özelliklerle tanımlaması ve bunu belgelerinde belirtmesi önerilir.
islocked(lock)veri yarışı içermemelidir.- Eğer
islocked(lock)falsedönerse, diğer görevlerden herhangi bir müdahale yoksatrylock(lock)'ın hemen çağrılması başarılı olmalıdır (truedöner).
Base.ReentrantLock — TypeReentrantLock()Bir Task senkronizasyonu için yeniden giriş kilidi oluşturur. Aynı görev, gerektiği kadar kilidi alabilir (bu, adın "Yeniden Giriş" kısmının anlamıdır). Her lock bir unlock ile eşleşmelidir.
lock çağrısı, ilgili unlock'a kadar o iş parçacığında sonlandırıcıların çalışmasını da engelleyecektir. Aşağıda gösterilen standart kilit deseninin doğal olarak desteklenmesi gerekir, ancak deneme/kilit sırasını tersine çevirmekten veya deneme bloğunu tamamen atlamaktan (örneğin, kilit hala tutulurken geri dönmeye çalışmak) kaçının:
Bu, kilit/açma çağrıları üzerinde bir alma/serbest bırakma bellek sıralaması sağlar.
lock(l)
try
<atomik iş>
finally
unlock(l)
endEğer !islocked(lck::ReentrantLock) geçerliyse, trylock(lck) başarılı olur, aksi takdirde kilidi "aynı anda" tutmaya çalışan başka görevler varsa başarısız olur.
Base.@lock — Macro@lock l exprlock(f, l::AbstractLock) makrosunun f fonksiyonu yerine expr ile versiyonudur. Aşağıdakine genişler:
lock(l)
try
expr
finally
unlock(l)
endBu, lock kullanarak bir do bloğu ile benzer, ancak bir kapanış oluşturmaktan kaçınır ve böylece performansı artırabilir.
@lock, Julia 1.3'te eklendi ve Julia 1.10'da dışa aktarıldı.
Base.Lockable — TypeLockable(value, lock = ReentrantLock())
value ile birlikte sağlanan lock ile ilişkilendirilmiş bir Lockable nesnesi oluşturur. Bu nesne @lock, lock, trylock, unlock destekler. Değere erişmek için, kilidi tutarken kilitlenebilir nesneyi indeksleyin.
En az Julia 1.11 gerektirir.
Örnek
julia> locked_list = Base.Lockable(Int[]);
julia> @lock(locked_list, push!(locked_list[], 1)) # değere erişmek için kilidi tutmalısınız
1-element Vector{Int64}:
1
julia> lock(summary, locked_list)
"1-element Vector{Int64}"Channels
Base.AbstractChannel — TypeAbstractChannel{T}T türündeki nesneleri ileten bir kanalın temsili.
Base.Channel — TypeChannel{T=Any}(size::Int=0)T türünde size nesnesini tutabilen bir Channel oluşturur. Dolu bir kanalda put! çağrıları, bir nesne take! ile çıkarılana kadar bloklanır.
Channel(0) tamponu olmayan bir kanal oluşturur. put!, eşleşen bir take! çağrılana kadar bloklanır. Ve tersine.
Diğer yapıcılar:
Channel(): varsayılan yapıcı,Channel{Any}(0)ile eşdeğerdirChannel(Inf):Channel{Any}(typemax(Int))ile eşdeğerdirChannel(sz):Channel{Any}(sz)ile eşdeğerdir
Varsayılan yapıcı Channel() ve varsayılan size=0, Julia 1.3'te eklendi.
Base.Channel — MethodChannel{T=Any}(func::Function, size=0; taskref=nothing, spawn=false, threadpool=nothing)func'dan yeni bir görev oluşturun, bunu T türünde ve size boyutunda yeni bir kanala bağlayın ve görevi, hepsini tek bir çağrıda planlayın. Görev sona erdiğinde kanal otomatik olarak kapatılır.
func, bağlı kanalı tek argümanı olarak kabul etmelidir.
Oluşturulan göreve bir referansa ihtiyacınız varsa, anahtar argüman taskref aracılığıyla bir Ref{Task} nesnesi geçirin.
Eğer spawn=true ise, func için oluşturulan Task, paralel olarak başka bir iş parçacığında planlanabilir; bu, bir görevi Threads.@spawn aracılığıyla oluşturmakla eşdeğerdir.
Eğer spawn=true ve threadpool argümanı ayarlanmamışsa, varsayılan olarak :default olur.
Eğer threadpool argmanı ayarlanmışsa (:default veya :interactive olarak), bu spawn=true anlamına gelir ve yeni Görev belirtilen iş parçacığı havuzuna oluşturulur.
Bir Channel döndürün.
Örnekler
julia> chnl = Channel() do ch
foreach(i -> put!(ch, i), 1:4)
end;
julia> typeof(chnl)
Channel{Any}
julia> for i in chnl
@show i
end;
i = 1
i = 2
i = 3
i = 4Oluşturulan görevi referans alma:
julia> taskref = Ref{Task}();
julia> chnl = Channel(taskref=taskref) do ch
println(take!(ch))
end;
julia> istaskdone(taskref[])
false
julia> put!(chnl, "Hello");
Hello
julia> istaskdone(taskref[])
truespawn= parametresi Julia 1.3'te eklendi. Bu yapıcı Julia 1.3'te eklendi. Daha önceki Julia sürümlerinde, Channel size ve T'yi ayarlamak için anahtar argümanlar kullanıyordu, ancak bu yapıcılar kullanımdan kaldırılmıştır.
threadpool= argümanı Julia 1.9'da eklendi.
julia> chnl = Channel{Char}(1, spawn=true) do ch
for c in "hello world"
put!(ch, c)
end
end
Channel{Char}(1) (2 items available)
julia> String(collect(chnl))
"hello world"Base.put! — Methodput!(c::Channel, v)Kanal c'ye bir öğe v ekler. Kanal doluysa engeller.
Tamponlanmamış kanallar için, farklı bir görev tarafından take! gerçekleştirilene kadar engeller.
v, put! çağrıldığında kanalın türüne convert ile dönüştürülür.
Base.take! — Methodtake!(c::Channel)Bir Channel içinden sırayla bir değeri kaldırır ve döndürür. Veri mevcut olana kadar engeller. Tamponlanmamış kanallar için, başka bir görev tarafından bir put! gerçekleştirilene kadar engeller.
Örnekler
Tamponlu kanal:
julia> c = Channel(1);
julia> put!(c, 1);
julia> take!(c)
1Tamponsuz kanal:
julia> c = Channel(0);
julia> task = Task(() -> put!(c, 1));
julia> schedule(task);
julia> take!(c)
1Base.isready — Methodisready(c::Channel)Bir Channel içinde bir değer olup olmadığını belirler. Hemen döner, engellemez.
Tamponlanmamış kanallar için, put! üzerinde bekleyen görevler varsa true döner.
Örnekler
Tamponlu kanal:
julia> c = Channel(1);
julia> isready(c)
false
julia> put!(c, 1);
julia> isready(c)
trueTamponlanmamış kanal:
julia> c = Channel();
julia> isready(c) # hiçbir görev put! için beklemiyor!
false
julia> task = Task(() -> put!(c, 1));
julia> schedule(task); # bir put! görevini planla
julia> isready(c)
trueBase.fetch — Methodfetch(c::Channel)İlk mevcut öğeyi Channel'dan (kaldırmadan) bekler ve döndürür. Not: fetch, bir tamponlanmamış (0-boyutlu) Channel üzerinde desteklenmez.
Örnekler
Tamponlu kanal:
julia> c = Channel(3) do ch
foreach(i -> put!(ch, i), 1:3)
end;
julia> fetch(c)
1
julia> collect(c) # öğe kaldırılmaz
3-element Vector{Any}:
1
2
3Base.close — Methodclose(c::Channel[, excp::Exception])Bir kanalı kapat. Bir istisna (isteğe bağlı olarak excp ile verilen) aşağıdakilerden biri tarafından fırlatılır:
Base.bind — Methodbind(chnl::Channel, task::Task)chnl'nin ömrünü bir görevle ilişkilendirir. Channel chnl, görev sona erdiğinde otomatik olarak kapatılır. Görevde yakalanmamış herhangi bir istisna, chnl üzerindeki tüm bekleyenlere iletilir.
chnl nesnesi, görev sona ermesinden bağımsız olarak açıkça kapatılabilir. Sona eren görevler, zaten kapatılmış Channel nesneleri üzerinde hiçbir etkiye sahip değildir.
Bir kanal birden fazla göreve bağlandığında, ilk sona eren görev kanalı kapatır. Aynı göreve bağlı birden fazla kanal olduğunda, görevin sona ermesi tüm bağlı kanalları kapatır.
Örnekler
julia> c = Channel(0);
julia> task = @async foreach(i->put!(c, i), 1:4);
julia> bind(c,task);
julia> for i in c
@show i
end;
i = 1
i = 2
i = 3
i = 4
julia> isopen(c)
falsejulia> c = Channel(0);
julia> task = @async (put!(c, 1); error("foo"));
julia> bind(c, task);
julia> take!(c)
1
julia> put!(c, 1);
HATA: TaskFailedException
Stacktrace:
[...]
nested task error: foo
[...]Low-level synchronization using schedule and wait
schedule en kolay doğru kullanımı henüz başlamamış (planlanmış) bir Task üzerindedir. Ancak, 4d61726b646f776e2e436f64652822222c20227363686564756c652229_40726566 ve wait senkronizasyon arayüzleri oluşturmak için çok düşük seviyeli bir yapı taşı olarak kullanılabilir. schedule(task) çağrısının kritik bir ön koşulu, çağrının task'ı "sahiplenmesi" gerektiğidir; yani, schedule(task) çağrısını yapan kodun, verilen task içindeki wait çağrısının nerelerde gerçekleştiğini bilmesi gerekir. Bu tür bir ön koşulu sağlamak için bir strateji, aşağıdaki örnekte gösterildiği gibi atomikler kullanmaktır:
@enum OWEState begin
OWE_EMPTY
OWE_WAITING
OWE_NOTIFYING
end
mutable struct OneWayEvent
@atomic state::OWEState
task::Task
OneWayEvent() = new(OWE_EMPTY)
end
function Base.notify(ev::OneWayEvent)
state = @atomic ev.state
while state !== OWE_NOTIFYING
# Spin until we successfully update the state to OWE_NOTIFYING:
state, ok = @atomicreplace(ev.state, state => OWE_NOTIFYING)
if ok
if state == OWE_WAITING
# OWE_WAITING -> OWE_NOTIFYING transition means that the waiter task is
# already waiting or about to call `wait`. The notifier task must wake up
# the waiter task.
schedule(ev.task)
else
@assert state == OWE_EMPTY
# Since we are assuming that there is only one notifier task (for
# simplicity), we know that the other possible case here is OWE_EMPTY.
# We do not need to do anything because we know that the waiter task has
# not called `wait(ev::OneWayEvent)` yet.
end
break
end
end
return
end
function Base.wait(ev::OneWayEvent)
ev.task = current_task()
state, ok = @atomicreplace(ev.state, OWE_EMPTY => OWE_WAITING)
if ok
# OWE_EMPTY -> OWE_WAITING transition means that the notifier task is guaranteed to
# invoke OWE_WAITING -> OWE_NOTIFYING transition. The waiter task must call
# `wait()` immediately. In particular, it MUST NOT invoke any function that may
# yield to the scheduler at this point in code.
wait()
else
@assert state == OWE_NOTIFYING
# Otherwise, the `state` must have already been moved to OWE_NOTIFYING by the
# notifier task.
end
return
end
ev = OneWayEvent()
@sync begin
@async begin
wait(ev)
println("done")
end
println("notifying...")
notify(ev)
end
# output
notifying...
doneOneWayEvent, bir görevin başka bir görevin notify'sini beklemesine izin verir. Bu, wait'in tek bir görevden yalnızca bir kez kullanılabileceği için sınırlı bir iletişim arayüzüdür (not: ev.task'ın atomik olmayan ataması).
Bu örnekte, notify(ev::OneWayEvent) yalnızca o OWE_WAITING durumunu OWE_NOTIFYING durumuna değiştiriyorsa schedule(ev.task) çağrısına izin verilir. Bu, wait(ev::OneWayEvent) işlemini gerçekleştiren görevin artık ok dalında olduğunu ve @atomicreplace(ev.state, state => OWE_NOTIFYING) işleminin başarısız olacağı için schedule(ev.task) çağrısında bulunan başka görevlerin olamayacağını bilmemizi sağlar.