Я прочитал эту статью Ceki и был заинтересован в том, каким может быть получение смещенного семафора (поскольку я чувствовал, что поведение "смещенной блокировки" будет иметь смысл и в семафорах ...).На моем оборудовании с двумя процессорами и Sun JVM 1.6 это фактически приводит к довольно равномерной аренде.
В любом случае, я также пытался «сместить» аренду семафора с помощью стратегии, которую я написал в другом ответе.Получается, что простое дополнительное выражение yield
приводит к значительному смещению.Ваша проблема более сложна, но, возможно, вы можете провести аналогичные тесты с вашей идеей и посмотреть, что вы получите:)
ПРИМЕЧАНИЕ Код ниже основан на коде Ceki здесь
Код:
import java.util.concurrent.*;
public class BiasedSemaphore implements Runnable {
static ThreadLocal<Boolean> favored = new ThreadLocal<Boolean>(){
private boolean gaveOut = false;
public synchronized Boolean initialValue(){
if(!gaveOut){
System.out.println("Favored " + Thread.currentThread().getName());
gaveOut = true;
return true;
}
return false;
}
};
static int THREAD_COUNT = Runtime.getRuntime().availableProcessors();
static Semaphore SEM = new Semaphore(1);
static Runnable[] RUNNABLE_ARRAY = new Runnable[THREAD_COUNT];
static Thread[] THREAD_ARRAY = new Thread[THREAD_COUNT];
private int counter = 0;
public static void main(String args[]) throws InterruptedException {
printEnvironmentInfo();
execute();
printResults();
}
public static void printEnvironmentInfo() {
System.out.println("java.runtime.version = "
+ System.getProperty("java.runtime.version"));
System.out.println("java.vendor = "
+ System.getProperty("java.vendor"));
System.out.println("java.version = "
+ System.getProperty("java.version"));
System.out.println("os.name = "
+ System.getProperty("os.name"));
System.out.println("os.version = "
+ System.getProperty("os.version"));
}
public static void execute() throws InterruptedException {
for (int i = 0; i < THREAD_COUNT; i++) {
RUNNABLE_ARRAY[i] = new BiasedSemaphore();
THREAD_ARRAY[i] = new Thread(RUNNABLE_ARRAY[i]);
System.out.println("Runnable at "+i + " operated with "+THREAD_ARRAY[i]);
}
for (Thread t : THREAD_ARRAY) {
t.start();
}
// let the threads run for a while
Thread.sleep(10000);
for (int i = 0; i< THREAD_COUNT; i++) {
THREAD_ARRAY[i].interrupt();
}
for (Thread t : THREAD_ARRAY) {
t.join();
}
}
public static void printResults() {
System.out.println("Ran with " + THREAD_COUNT + " threads");
for (int i = 0; i < RUNNABLE_ARRAY.length; i++) {
System.out.println("runnable[" + i + "]: " + RUNNABLE_ARRAY[i]);
}
}
public void run() {
while (!Thread.currentThread().isInterrupted()) {
if (favored.get()) {
stuff();
} else {
Thread.yield();
// try {
// Thread.sleep(1);
// } catch (InterruptedException e) {
// Thread.currentThread().interrupt();
// }
stuff();
}
}
}
private void stuff() {
if (SEM.tryAcquire()) {
//favored.set(true);
counter++;
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
SEM.release();
} else {
//favored.set(false);
}
}
public String toString() {
return "counter=" + counter;
}
}
Результаты:
java.runtime.version = 1.6.0_21-b07
java.vendor = Sun Microsystems Inc.
java.version = 1.6.0_21
os.name = Windows Vista
os.version = 6.0
Runnable at 0 operated with Thread[Thread-0,5,main]
Runnable at 1 operated with Thread[Thread-1,5,main]
Favored Thread-0
Ran with 2 threads
runnable[0]: counter=503
runnable[1]: counter=425
Пробовал 30 секунд вместо 10:
java.runtime.version = 1.6.0_21-b07
java.vendor = Sun Microsystems Inc.
java.version = 1.6.0_21
os.name = Windows Vista
os.version = 6.0
Runnable at 0 operated with Thread[Thread-0,5,main]
Runnable at 1 operated with Thread[Thread-1,5,main]
Favored Thread-1
Ran with 2 threads
runnable[0]: counter=1274
runnable[1]: counter=1496
PS: Похоже, "тусоваться" было очень плохой идеей.Когда я попытался вызвать SEM.tryAcquire(1,TimeUnit.MILLISECONDS);
для избранных тем и SEM.tryAcquire()
для непривилегированных тем, непривилегированные потоки получили разрешение почти в 5 раз больше, чем избранная тема!
Кроме того, я хотел бы добавитьчто эти результаты измеряются только в одной конкретной ситуации, поэтому неясно, как эти меры ведут себя в других ситуациях.