All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wildfly.common.lock.SpinLock Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

The newest version!
/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2018 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.wildfly.common.lock;

import static org.wildfly.common.lock.JDKSpecific.unsafe;

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;

import org.wildfly.common.Assert;
import org.wildfly.common.cpu.ProcessorInfo;

/**
 * A spin lock.  Such locks are designed to only be held for a very short time - for example, long enough to compare and
 * swap two fields.  The lock may degrade to yielding the thread after a certain number of spins if it is held for too long.
 * 

* Spin locks do not support conditions, and they do not support timed waiting. Normally only the uninterruptible {@code lock}, * {@code tryLock}, and {@code unlock} methods should be used to control the lock. */ public class SpinLock implements ExtendedLock { private static final long ownerOffset; private static final int defaultSpinLimit; static { try { ownerOffset = unsafe.objectFieldOffset(SpinLock.class.getDeclaredField("owner")); } catch (NoSuchFieldException e) { throw new NoSuchFieldError(e.getMessage()); } defaultSpinLimit = AccessController.doPrivileged( (PrivilegedAction) () -> Integer.valueOf( System.getProperty("jboss.spin-lock.limit", ProcessorInfo.availableProcessors() == 1 ? "0" : "5000") ) ).intValue(); } @SuppressWarnings("unused") private volatile Thread owner; private int level; private final int spinLimit; /** * Construct a new instance. */ public SpinLock() { this(defaultSpinLimit); } /** * Construct a new instance with the given spin limit. * * @param spinLimit the spin limit to use for this instance */ public SpinLock(final int spinLimit) { Assert.checkMinimumParameter("spinLimit", 0, spinLimit); this.spinLimit = spinLimit; } /** * Determine if this spin lock is held. Useful for assertions. * * @return {@code true} if the lock is held by any thread, {@code false} otherwise */ public boolean isLocked() { return owner != null; } /** * Determine if this spin lock is held by the calling thread. Useful for assertions. * * @return {@code true} if the lock is held by the calling thread, {@code false} otherwise */ public boolean isHeldByCurrentThread() { return owner == Thread.currentThread(); } /** * Determine if this lock is fair. * * @return {@code true}; the lock is fair */ public boolean isFair() { return true; } /** * Acquire the lock by spinning until it is held. */ public void lock() { Thread owner; int spins = 0; for (;;) { owner = this.owner; if (owner == Thread.currentThread()) { level++; return; } else if (owner == null && unsafe.compareAndSwapObject(this, ownerOffset, null, Thread.currentThread())) { level = 1; return; } else if (spins >= spinLimit) { Thread.yield(); } else { JDKSpecific.onSpinWait(); spins++; } } } /** * Acquire the lock by spinning until it is held or the thread is interrupted. * * @throws InterruptedException if the thread is interrupted before the lock can be acquired */ public void lockInterruptibly() throws InterruptedException { Thread owner; int spins = 0; for (;;) { if (Thread.interrupted()) throw new InterruptedException(); owner = this.owner; if (owner == Thread.currentThread()) { level++; return; } else if (owner == null && unsafe.compareAndSwapObject(this, ownerOffset, null, Thread.currentThread())) { level = 1; return; } else if (spins >= spinLimit) { Thread.yield(); } else { JDKSpecific.onSpinWait(); spins++; } } } /** * Try to acquire the lock, returning immediately whether or not the lock was acquired. * * @return {@code true} if the lock was acquired, {@code false} otherwise */ public boolean tryLock() { Thread owner = this.owner; if (owner == Thread.currentThread()) { level++; return true; } else if (owner == null && unsafe.compareAndSwapObject(this, ownerOffset, null, Thread.currentThread())) { level = 1; return true; } else { return false; } } /** * Release the lock. * * @throws IllegalMonitorStateException if the lock is not held by the current thread */ public void unlock() { Thread owner = this.owner; if (owner == Thread.currentThread()) { if (--level == 0) this.owner = null; } else { throw new IllegalMonitorStateException(); } } /** * Unsupported. * * @param time ignored * @param unit ignored * @return nothing * @throws UnsupportedOperationException always */ public boolean tryLock(final long time, final TimeUnit unit) throws UnsupportedOperationException { throw Assert.unsupported(); } /** * Unsupported. * * @return nothing * @throws UnsupportedOperationException always */ public Condition newCondition() throws UnsupportedOperationException { throw Assert.unsupported(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy