2009-02-17 21 views
43

Javascript'te atomik bir test-set, semafor veya kilit gibi bir şey var mı?Javascript semafor/test-ve-set/kilitleme?

Özel bir iletişim kuralı (arka plan işlemi, tarayıcıyla ilgisi olmayan ayrı bir işlemde tam olarak çalışır) aracılığıyla eşzamansız arka plan işlemlerini çağıran javascript'im var. Bir yarış durumuna girdiğime inanıyorum; arka plan işlemi benim testim ile setim arasında döner ve javascript tarafında işler yapar. Gerçek bir semafor haline getirmek için test-ve-set işlemine ihtiyacım var.

Burada arka plan işlemleri tespit etmek ve bunları sıraya çalışır javascript kodu var:

Call = function() { 

var isRunning = true, 
    queue = []; 

return { 
    // myPublicProperty: "something", 

    call: function (method) { 
      if (isRunning) { 
       console.log("Busy, pushing " + method); 
       queue.push(method); 
      } else { 
       isRunning = true; 
       objccall(method); 
      } 
     }, 

     done: function() { 
      isRunning = false; 
      if (queue.length > 0) { 
       Call.call(queue.shift()); 
      } 
     } 
    }; 
}(); 

Çağrı sıraya uygulayan tek olduğu; Harici bir işlemi çağırmak isteyen herkes Call.call ("bir şey") yapar.

Herhangi bir fikrin var mı? Eğer bir çerçeve böyle kullanıyorsanız

+0

'Prosesinizin ne olduğunu daha ayrıntılı olarak belirtmek isteyebilirsiniz. Bu sunucu tarafı javascript mi? –

+2

Javascript kodu her zaman atomiktir, bu nedenle kilitlemeye veya herhangi bir şey yapmaya gerek yoktur. [Neden javascript'te eşzamanlılık kontrol aracımız yok?] (Http://uzairfarooq.github.io/why-no-concurrency-control-tool-in-javascript/). –

cevap

2

Belki) =

/sadece DOM ve kilide değişken eklemek, temel bir tamsayı semaforu uygulamak kilidini ve fonksiyonları başka, bunu kontrol etmeyi sürdürmek onları zaman aşımı emin olabilir Mootools olarak, uygulamanın akışını onComplete gibi olaylarla işlemeyi deneyebilirsiniz.

18

JS'nin çok parçalı bir dil olmadığından JavaScript'in kilit dili yoktur. Birden çok iş parçacığı yalnızca aynı anda tamamen farklı bağlamlarda çalışabilir - örn. HTML5 İşçi iş parçacığı veya JavaScriptCore API'sının bağlam nesnesinin birden çok örneğinde olduğu gibi (ÖrümcekMonkey'in benzer bir konsepti olduğunu varsayalım). Paylaşılan devlet olamazlar, bu nedenle özünde tüm uygulama atomiktir. Böyle (uygun API'leri kullanarak)

External Process: 
<JSObject>.isRunning = true; 
doSomething() 
<JSObject>.done() 

Veya bazı:

Tamam, şimdi kodunun bir kısmını sağlamış olarak i benzeyen bir şey var varsayalım. Bu durumda JS'nin js nesnesinin bağlamında (JavaScriptCore'un yaptığı gibi) yürütülmesi durumunda JS motorunun engellenmesini beklerdim, bu da muhtemelen js uygulamasının etrafında bir manüel kilit yerleştirmeniz gerekmeyeceği için başarısız olur.

Tüm bunları yapmak için hangi motoru kullanıyorsunuz? Sorunuma göre, açıklamanıza bağlı olarak, söz konusu dil tarafından sağlanan C/C++ API'sini kullanarak JS olmayan bir dilden ikincil bir iş parçacığından bir bayrak ayarlamışsınız gibi görünmektedir ve çoğu JS motoru API aracılığıyla yapılan herhangi bir durum denetiminin olduğunu varsayar. Tek bir iş parçacığı üzerinde, genellikle tüm yürütme üzerinde gerçekleşen aynı iş parçacığı üzerinde oluşuyor.

+0

Biraz daha net hale getirmek için yukarıdaki kodun tamamını ekledim. Motor Webkit (safari). Javascript'ten dış süreçleri çağırıyorum ve bittiğinde dış işlem "tamamlandı" yöntemini çağırıyor. Temel olarak, bir seferde sadece bir harici işlemin çalıştığından emin olmalıyım. – Parand

+0

[someObject çağrısı] veya JSObjectCallAsFunction (context, doneFunction, someObject) ile benzer bir şey yaptığınızı varsayarak, özellikle de WebKit tarafından sağlanan ObjC JS API'sini kullanıyorsanız ana iletiyi aradığınızdan emin olmalısınız (IIRC bazı kilitleri engelleyebilir) – olliej

+0

iPhone'da webkit sdk'yi herhangi bir şansla kullandınız mı? Basit bir window.location düzeni kullanıyorum, SDK'yı denemedim. SDK hakkında daha fazla bilgi edinmek isterim. – Parand

0

Seçme listelerini dolduran ajax içeriklerim var, kilitlenmeye ihtiyacım vardı, bu yüzden böyle bir şey yaptım. Sanırım ertelemeler, borular ya da başka şeyler kullanmanın daha kolay olduğunu düşünebilirsiniz. o javaScript dişli tek olduğu doğrudur iken şeyden önce

var semaphore=[]; 

function myFunc(arg){ 
    var dfd; 
    $.when(semaphore[table]).done(
     function(){ 
      dfd=myFuncInner(arg); 
     } 
    ); 
return dfd; 
} 

function myFuncInner(table){ 
semaphore[arg] = new $.Deferred(); 
... 
somethingasynchronous({ 
    semaphore[arg].resolve(); 
}); 

return semaphore[arg]; 
} 
0

, hiçbir serileştirme mekanizması hiç bir javaScript uygulamasının gerektirdiği doğrudur DEĞİLDİR.

Basit bir örnek, bir sunucuya Ajax isteğinin çalıştığı belirli bir süre boyunca gönderme düğmesinin ne zaman sönmesi gerektiğidir. Eşzamansız Ajax isteği başarıyla tamamlandığında, düğmenin bulunduğu yerde bir mesaj görünmelidir.

Düğmenin etkinliğini iptal edebilmek ve Ajax isteği tamamlanır tamamlanmaz stilini "göster: yok" olarak ayarlamanız güzel olsa da jQuery'de bu mümkün değildir. Ayrıca, bir çözüm, iki eş zamanlı aktiviteyi senkronize etmek için Olayları kullanabilir, ancak bu basit bir problem için aşırı derecede önemlidir.

Düşük teknoloji ürünü bir çözüm, bir kilidi yoklamaktır ve geri yükleme tamamlandığında kilidi açılır, ancak "sunucu bitti" mesajı, $ .post tarafından belirlenen başarı geri çağrısı gerçekleştirilinceye kadar görüntülenmez.

var gl_lock; 
var gl_selfID; 

function poll_lock(message) { 
    if (gl_lock === 0) { 
      $('#output').text(message).fadeIn(200); 
      window.clearInterval(gl_selfID); 
    } 
} // end of poll_lock 

function worker() { 

    // no one gets in or out 
    gl_lock = 1; 

    $.post(..., data,function() { 
      gl_selfID = window.setInterval(poll_lock, 40, data.message); 
     }, "json"); 

    // end of fadeout unlock the semaphore 
    $('#submit-button').fadeOut(400, function() { gl_lock = 0; }); 

    } // end of worker 

Son olarak, çizgiler daha önce perrohunter bu tartışmada öne birlikte bu, daha detaylı bir cevap olduğunu düşünüyorum.