জাভাতে কি কোনও মুটেক্স রয়েছে?


110

জাভাতে কোনও মুটেক্স অবজেক্ট আছে বা এটি তৈরির উপায় আছে? আমি জিজ্ঞাসা করছি কারণ 1 পারমিটের সাহায্যে আরম্ভ করা একটি সেমফোর অবজেক্ট আমাকে সাহায্য করে না। এই ক্ষেত্রেটি চিন্তা করুন:

try {
   semaphore.acquire();
   //do stuff
   semaphore.release();
} catch (Exception e) {
   semaphore.release();
}

প্রথম অর্জনে যদি কোনও ব্যতিক্রম ঘটে, তবে ক্যাচ ব্লকের রিলিজটি পারমিটগুলিকে বাড়িয়ে তুলবে, এবং সেমফোর আর বাইনারি সেমফোর হয় না।

সঠিক উপায় কি হবে?

try {
   semaphore.acquire();
   //do stuff
} catch (Exception e) {
   //exception stuff
} finally {
   semaphore.release();
}

উপরের কোডটি নিশ্চিত করবে যে সেমফোর বাইনারি হবে?


Java.util.concurrent.locks.AbstractQueuedSynchronizer এর জন্য জাভাডোকটি দেখুন। এটিতে একটি মুটেক্স ক্লাস কীভাবে লিখতে হয় তার একটি উদাহরণ রয়েছে। -বেডনার
জো

আপনি কি এই আচরণটি অনুগতভাবে খুঁজে পেয়েছেন? 1-পারমিট সেম্যাফোরে রিলিজ () প্রকাশের বাস্তবায়ন কী এমন একটি অতিরিক্ত পারমিট যুক্ত করে যদিও এটি বর্তমানে অন্য একটি ধারণ করে?
স্নিগ্ধিক

উত্তর:


112

এই পৃষ্ঠাটি দেখুন: http://www.oracle.com/technetwork/articles/javase/index-140767.html

এটির কিছুটা আলাদা প্যাটার্ন রয়েছে যা আপনি যা খুঁজছেন তা (আমার মনে হয়):

try {
  mutex.acquire();
  try {
    // do something
  } finally {
    mutex.release();
  }
} catch(InterruptedException ie) {
  // ...
}

এই ব্যবহারে, আপনি কেবল release()সফল পরে কল করছেনacquire()


133

জাভাতে যে কোনও অবজেক্ট synchronizedব্লক ব্যবহার করে লক হিসাবে ব্যবহার করা যেতে পারে । এটি ব্যতিক্রম ঘটলে স্বয়ংক্রিয়ভাবে লকটি ছেড়ে দেওয়ার যত্ন নেবে।

Object someObject = ...;

synchronized (someObject) {
  ...
}

আপনি এখানে এ সম্পর্কে আরও পড়তে পারেন: অন্তর্নিহিত লক্স এবং সিঙ্ক্রোনাইজেশন


আমি একটি semaphore ব্যবহার করতে চেয়েছিলেন খুব সহায়ক কিনতে।
নোয়াম নেভো

11
@ নোয়াম: কেবলমাত্র সেমোফোরের সাথে এবং এর সাথে কোডটি তুলনা করুন synchronized, আপনি আরও ভাল পাঠযোগ্য এবং কম ত্রুটি-প্রবণ কি দেখতে পাবেন।
ভ্লাদ

17
সিঙ্ক্রোনাইজ করা কীওয়ার্ডটি ব্যবহার করা যাবে না যদি আপনি লকটি অন্য কোনও পদ্ধতিতে ছাড়ার আশা করেন (উদাঃ transaction.begin(); transaction.commit())।
হোসাম অলি

এবং এটি অবজেক্ট অরিয়েন্টেড..এই অনেক নিম্ন স্তরের সিঙ্ক্রোনাইজেশন
আনশুলকত্ত

এছাড়াও দেখব someObject.wait(timeout)এবং someObject.notify()আপনি এই উত্তর কোড দিকে তাকিয়ে করছেন।
ড্যানিয়েল এফ

25
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


private final Lock _mutex = new ReentrantLock(true);

_mutex.lock();

// your protected code here

_mutex.unlock();

5
ইতিমধ্যে সরবরাহিত সমাধানগুলির থেকে এটি কীভাবে উন্নত? আসল প্রশ্নকারী যে সমস্যার মুখোমুখি হয়েছিল তা কীভাবে সমাধান করবে?
মার্টিন

@ মার্টিন:, "Lock implementations provide more extensive locking operations than can be obtained using synchronized methods and statements."থেকে: ডকস.ওরকল / জাভাসে / / / ডকস / এপি / জাভা / ইউটিল / কনকন্টেন্ট / লকস / ......... ... যদিও আপনার একটি বক্তব্য রয়েছে। আরগভের উত্তর এই ক্রিয়াকলাপগুলিকে চিত্রিত বা ব্যাখ্যা করে না।
হতাশ

3
এটি একটি পুনরাবৃত্তিমায়িত মুটেক্স যা একই থ্রেড থেকে একাধিক পুনরায় লক অনুমতি দেবে, যা সমস্যাযুক্ত হতে পারে। একটি "সত্য", বেসিক মিউটেক্স (অ-পুনরাবৃত্ত, সি ++ - শৈলী) একবারে কেবলমাত্র একটি লকের অনুমতি দেয়। আপনি যদি আপনার লাইনটি এতে পরিবর্তন করেন তবে আপনি থ্রেডের পুনরায় তালার সংখ্যা ফিরে পেতে getHoldCount ()private final ReentrantLock _mutex = ... ব্যবহার করতে পারেন । ( এটি প্রতিরোধের জন্য আপনি একটি প্রয়োগ করতে পারেন the এপিআই দেখুন ))Condition
এনট্যাংলডলুপস

16

এটির স্পষ্টরূপে কেউ উল্লেখ করেনি, তবে এই ধরণের প্যাটার্নটি সাধারণত সমুদ্রের জন্য উপযুক্ত নয়। কারণ যে কোনো থ্রেড একটি সেমফোর্ মুক্তি পারেন, কিন্তু আপনি সাধারণত চান মালিক থ্রেড যে মূলত আনলক পাবে লক । এই ব্যবহারের ক্ষেত্রে, জাভাতে আমরা সাধারণত রেন্টেন্টলকস ব্যবহার করি, যা এ জাতীয়ভাবে তৈরি করা যেতে পারে:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

private final Lock lock = new ReentrantLock(true);

এবং ব্যবহারের সাধারণ ডিজাইনের ধরণটি হ'ল:

  lock.lock();
  try {
      // do something
  } catch (Exception e) {
      // handle the exception
  } finally {
      lock.unlock();
  }

এখানে জাভা উত্স কোডের একটি উদাহরণ যেখানে আপনি এই নিদর্শনটি কার্যত দেখতে পাচ্ছেন।

প্রত্যাশিত লকগুলির মধ্যে ন্যায়বিচারকে সমর্থন করার অতিরিক্ত সুবিধা রয়েছে।

আপনার অ-মালিকানা-প্রকাশের শব্দার্থবিজ্ঞানের প্রয়োজন হলে কেবলমাত্র সেমফোরগুলি ব্যবহার করুন।


5
আসলে এই প্রশ্নের এই (কেবলমাত্র) সঠিক উত্তর হওয়া উচিত। সেমফোর এবং পারস্পরিক বর্জনীয় লকটির মধ্যে পার্থক্যের স্পষ্ট ব্যাখ্যা। এর সাথে একটি সেমফোর ব্যবহার কোনও count=1পারস্পরিক বর্জনীয় লক নয়।
কাইহুয়া

3
খুশী কেউ নির্দেশ করলেন। কোনও রিসোর্সটিতে একচেটিয়া অ্যাক্সেসের জন্য মিউটেক্সগুলি হ'ল উপায়। বাইনারি semaphores mutex নয়, semaphores সিগন্যালিং ব্যবস্থা হিসাবে আরও ব্যবহার করা উচিত।
শিবম ত্রিপাঠি

রুবল: সুতরাং lockযেমন ReentrantLockএকটি হয় mutex? আমি নিশ্চিত নই কেন mutexএবং কেন binary semaphoreএকই সত্তা হিসাবে সমান নেওয়া হচ্ছে। Semaphoreযে কোনও থ্রেড দ্বারা প্রকাশ করা যেতে পারে, যাতে এটি রক্ষণের গ্যারান্টি নাও দেয় critical section। কোন চিন্তা?
কৌতুহলী মন

@ কাইহুয়া: আপনার চিন্তা নিয়ে আমি অনুরণন করছি এই উত্তরটি মূল পার্থক্যটি এনেছে
কুরিজমাইন্ড

6

আমি মনে করি আপনার সাথে চেষ্টা করা উচিত:

সেমাফোরের সূচনা যখন:

Semaphore semaphore = new Semaphore(1, true);

এবং আপনার মধ্যে Runnable Implementation

try 
{
   semaphore.acquire(1);
   // do stuff

} 
catch (Exception e) 
{
// Logging
}
finally
{
   semaphore.release(1);
}

এইভাবেই আমি এটি করেছি, তবে এই পথে যাওয়ার উপায়টি কিনা আমি নিশ্চিত নই।
বিচ্ছিন্ন

1
ডকস.ওরাকল.com/javase/7/docs/api/java/util/concurrent/… এর মতে "কোনও অনুমতি নেই যে থ্রেডটি অবশ্যই কলটি অর্জনের মাধ্যমে সেই অনুমতিটি অর্জন করতে হবে। একটি সেমফোরের সঠিক ব্যবহার হ'ল অ্যাপ্লিকেশন প্রোগ্রামিং কনভেনশন দ্বারা প্রতিষ্ঠিত। " যদি অধিগ্রহণ ব্যতিক্রম ছুঁড়ে ফেলে, অবশেষে মুক্তিটি ভুলভাবে একটি অনুমতি ছেড়ে দেয়। এই থ্রেডের অন্যান্য উদাহরণগুলি সঠিক প্রবাহ দেখায়।
ব্রেন্ট কে।

3

মূল পোস্টে ভুলটি ট্রুপ লুপের অভ্যন্তরে () কল সেট অর্জন করা হয়। "বাইনারি" সেমোফোর (মিটেক্স) ব্যবহারের জন্য এখানে একটি সঠিক পদ্ধতি রয়েছে:

semaphore.acquire();
try {
   //do stuff
} catch (Exception e) {
   //exception stuff
} finally {
   semaphore.release();
}

1

একটি Semaphoreবাইনারি কিনা তা নিশ্চিত করার জন্য আপনাকে কেবল নিশ্চিত করতে হবে যে আপনি সেমফোর তৈরি করার সময় 1 হিসাবে পারমিটের সংখ্যায় পাস করেছেন। Javadocs একটি বিট আরো ব্যাখ্যা আছে।


1

প্রতিটি বস্তুর লকটি মুটেক্স / সেমফোর ডিজাইনের থেকে কিছুটা আলাদা। উদাহরণস্বরূপ, পূর্ববর্তী নোডের লক প্রকাশ এবং পরবর্তী ক্যাপচারের সাথে ট্র্যাভার্সিং লিঙ্কযুক্ত নোডগুলি সঠিকভাবে প্রয়োগ করার কোনও উপায় নেই। তবে মিটেক্সের সাহায্যে এটি কার্যকর করা সহজ:

Node p = getHead();
if (p == null || x == null) return false;
p.lock.acquire();  // Prime loop by acquiring first lock.
// If above acquire fails due to interrupt, the method will
//   throw InterruptedException now, so there is no need for
//   further cleanup.
for (;;) {
Node nextp = null;
boolean found;
try { 
 found = x.equals(p.item); 
 if (!found) { 
   nextp = p.next; 
   if (nextp != null) { 
     try {      // Acquire next lock 
                //   while still holding current 
       nextp.lock.acquire(); 
     } 
     catch (InterruptedException ie) { 
      throw ie;    // Note that finally clause will 
                   //   execute before the throw 
     } 
   } 
 } 
}finally {     // release old lock regardless of outcome 
   p.lock.release();
} 

বর্তমানে, এ ধরনের কোন ক্লাস হয় java.util.concurrent, কিন্তু আপনি Mutext বাস্তবায়ন এখানে পেতে পারেন Mutex.java । স্ট্যান্ডার্ড লাইব্রেরি হিসাবে, Semaphore এই সমস্ত কার্যকারিতা এবং আরও অনেক কিছু সরবরাহ করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.