14 Kasım 2017 Salı

thread Syncronization Sınıfları

barrier Sınıfı
Giriş
Şu satırı dahil ederiz.
#include <boost/thread/barrier.hpp>
Açıklaması şöyle
A barrier is a simple concept. Also known as a rendezvous, it is a synchronization point between multiple threads. The barrier is configured for a particular number of threads (n), and as threads reach the barrier they must wait until all n threads have arrived. Once the n-th thread has reached the barrier, all the waiting threads can proceed, and the barrier is reset.
Constructor
Şöyle yaparız.
boost::barrier barrier(3);
Şöyle yaparız.
boost::barrier barrier{2};
wait metodu
Şöyle yaparız.
boost::barrier barrier{2};
boost::thread t([&barrier] {
  barrier.wait();
  // actual thread code
});
condition_variable Sınıfı
condition_variable Sınıfı yazısına taşıdım.

locked_guard Sınıfı
Giriş
Şu satırı dahil ederiz.
#include <boost/thread.hpp>
Bu sınıf ile scoped_lock çok benzer gibi görünüyorlar. scoped_lock çok daha gelişmiş özellikler sunar.
Constructor
Şöyle yaparız.
boost::mutex m;

void Foo()
{
  boost::lock_guard<boost::mutex> guard (m);
  ...
}
mutex Sınıfı
Constructor
Şöyle yaparız.
boost::mutex m;
lock metodu
Şöyle yaparız. Bu metodu direkt çağırmak yerine mutex::scoped_lock ile kullanmak daha iyi.
m.lock();
unlock metodu
Şöyle yaparız.
m.unlock();
mutex::scoped_lock Sınıfı
Constructor
Şöyle yaparız.
boost::mutex m = ...;
...
{
  boost::mutex::scoped_lock lock (m);
  ...
}
recursive_mutex Sınıfı
Constructor
Şöyle yaparız.
boost::recursive_mutex m;
recursive_mutex::scoped_lock Sınıfı
Constructor
Şöyle yaparız.
boost::recursive_mutex m = ...;...
{
  boost::recursive_mutex::scoped_lock lock (m);
  ...
}
shared_mutex Sınıfı
Şu satırı dahil ederiz.
#include <boost/thread/shared_mutex.hpp>
Read/Write lock sağlar. Kolay kullanım için şu satırı dahil ederiz.
typedef boost::shared_mutex RWLock;
Linux'ta shared_mutex
lock sınıflar ve shared_mutex ayrılmaz ikili oldukları için Linux'a özgü bir açıklamayı yazıya dahil etmek istedim. Açıklam şöyle. Yani shared_mutex yoğun yük altında çok iyi çalışmayabilir.
The current (as of boost 1.59) implementation of boost::shared_mutex for 'pthread' is pretty suboptimal as it's using a heavyweight mutex to guard the internal mutex state... [when access concurrency is high] the shared mutex is effectively exclusive.
Constructor
Şöyle yaparız.
boost::shared_mutex m;
shared_lock Sınıfı - Read Lock
shared_lock Sınıfı yazısına taşıdım.

unique_lock Sınıfı - Write Lock
Şu satırı dahil ederiz.
#include <boost/thread/locks.hpp>
Şöyle bir typdef yapmak kodu okunaklı yapar.
typedef boost::unique_lock<boost::shared_mutex> WriteLock;
Şöyle yaparız.
void unconditional_writer()
{
  WriteLock lock(mutex);  // do work here, with exclusive access
}
Bu sınıf boost::mutex ile de çalışıyor. Şöyle yaparız.
boost::mutex _mutex;

void func () {
  boost::unique_lock<boost::mutex> lock(_mutex);  
    // modify data-structure
}
Constructor
Elimizde bir shared_mutex olsun.
typedef boost::shared_mutex RWock;
typedef boost::unique_lock< RWock > WriteLock;

RWLock mutex;
Write lock almak için şöyle yaparız.
void Foo::foo ()
{
  WriteLock w_lock (mutex);
  ...
}
upgrade_lock Sınıfı - Write lock olarak yükseltilebilen Read lock
Açıklaması şöyle. Aslında bu açıklama shared_mutex'e ait ancak lock sınıfı için de geçerli olduğu için yazıya dahil etttim.
The UpgradeLockable concept is a refinement of the SharedLockable concept that allows for upgradable ownership as well as shared ownership and exclusive ownership. This is an extension to the multiple-reader / single-write model provided by the SharedLockable concept: a single thread may have upgradable ownership at the same time as others have shared ownership.
İşlem sırası şöyle.
1. Writer takes a privileged lock, and starts checking the condition
2. Other threads may take shared locks
3. Writer has checked the condition which was satisfied, and upgrades to exclusive lock (must block until other locks have been released)
Önce bir Read Lock alır. Daha sonra bunu Write Lock tipine yükseltir. Şöyle yaparız.
void conditional_writer()
{
  boost::upgrade_lock< boost::shared_mutex > lock(mutex);
  // do work here, without anyone having exclusive access

  if (something) {
    boost::upgrade_to_unique_lock< boost::shared_mutex > uniqueLock(lock);
    // do work here, but now you have exclusive access
  }

  // do more work here, without anyone having exclusive access
}
Ya da şöyle yaparız.
void writer()
{
  // get upgradable access
  boost::upgrade_lock<boost::shared_mutex> lock(mutex);

  // get exclusive access
  boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
  // now we have exclusive access
}
Açıklaması şöyle.
The difference between upgrade_lock and unique_lock is simple. An instance of unique_lock is acquiring a full exclusive ownership of a shared_mutex. This means that no one else can get any type of ownership while the unique_lock is alive.

Unlike the unique_lock an instance of upgrade_lock is acquiring an upgrade ownership that exclusive only amongst threads trying to get the same upgrade ownership. All other threads that try to get a shared ownership could acquire it with no conflict until the upgrade_lock is upgraded to unique (with an instance of upgrade_to_unique_lock).

The upgrade_lock is useful when some of threads can be readers only and will not try to promote itself to writers. Otherwise (all readers may try to become writers at some point) upgrade_lock will operate as unique_lock.
Açıklaması şöyle.
shared_mutex exists only to supply the functionality of traditional read/write mutexes. Some clients will be understandably leery of a mutex changing lock-modes from one to another, and yet still need the traditional functionality of a rw/mutex. This is the role of shared_mutex.

Other clients will look at shared_mutex and say: I want more. I want to sometimes atomically upgrade my ownership from shared to exclusive. And this is the role of upgrade_mutex. upgrade_mutex is not better than shared_mutex, nor vice-versa. It is simply another tool in the toolbox.
Örnek
Şöyle yaparız
using UpgradeLock = boost::upgrade_lock<boost::shared_mutex>;
using UpgradeToUniqueLock = boost::upgrade_to_unique_lock<boost::shared_mutex>;

boost::shared_mutex mtx;

void DeleteTable(<tbl>) {
  UpgradeLock lock(mtx);
  if (<the table exists>) {
    UpgradeToUniqueLock up(lock); // (!)
    // delete the table
  }
}
bool try_lock_upgrade metodu
upgrade_lock sınıfının unique_lock olarak yükseltilmesinde zaman/süre kullanılabilir. Bu iş için iki metodu var. Bunlar şöyle.
bool try_lock_upgrade_for(duration d)
bool try_lock_upgrade_until(time when)

owns_lock metodu
Şöyle yaparız.
boost::upgrade_lock<boost::shared_mutex> lock = ...
assert(lock.owns_lock());
boost::upgrade_to_unique_lock  Sınıfı
Yukarıdaki yükseltilebilen Read lock'ı Write lock yapan sınıf. Örnek ver

Starvation
Starvation'a karşı tedbir olarak condition veya atomic sayaçlar kullanılabilir. Bazı örnekler şöyle.

Hiç yorum yok:

Yorum Gönder