Producer/Consumer programs
Style
Standard C# naming convention for methods is PascalCase. For static and instance members there are more variants around but often they are prefixed with _ and/or area also PascalCase so they can be easily distinguished from local variables and parameters. Following standard naming conventions makes your code look more familiar to other C# developers.
Structure
It is all static methods and global variables which seriously hurts maintenance and makes testing the code real painful as you probably have already discovered (I guess you have managed with a lot of commenting in and out code).
The easiest way to simplify this is to provide an abstract base class which the various implementations can derive from an implement. You should also pass the buffer size and values to produce/consume as parameters to break dependencies on global variables.
Something along these lines:
public class ProducerConsumerBase
{
    protected char[] _Buffer;
    protected int _TotalNumberOfValues;

    protected ProducerConsumerBase(int bufferSize, int totalNumberOfValues)
    {
        _Buffer = new char[buffSize];
        _TotalNumberOfValues = totalNumberOfValues;
    }
    
    public abstract void ProduceAll();
    public abstract void ConsumeAll();
}

this can then be derived like this:
public class BusyWaitingProducerConsumer : ProducerConsumerBase
{
    public BusyWaitingProducerConsumer(int bufferSize, int totalNumberOfValues)
        : base(bufferSize, totalNumberOfValues)
    {
    }
    
    public void ProduceAll()
    {
        ...
    }
    
    public void ConsumeAll()
    {
        ...
    }
}


public class SemaphoreProducerConsumer : ProducerConsumerBase
{
    public SemaphoreProducerConsumer (int bufferSize, int totalNumberOfValues)
        : base(bufferSize, totalNumberOfValues)
    {
    }
    
    public void ProduceAll()
    {
        ...
    }
    
    public void ConsumeAll()
    {
        ...
    }
}

The main method of your program then would be:
static const int BuffSize = 10;
static const int ValuesToProduce = 95;

static void Main(string[] args)
{
    var producerConsumer = new BusyWaitingProducerConsumer(BuffSize, ValuesToProduce);
    Thread p = new Thread(new ThreadStart(producerConsumer.Produce));
    Thread c = new Thread(new ThreadStart(producerConsumer.Consume));
    p.Start();
    c.Start();
}

And you can easily swap out the concrete implementation you want to test with without having to change or comment out a lot of code.
Bugs
Your busy-waiting implementation is broken in that you will need to at least call Interlocked.Increment and Interlocked.Decrement on avail because ++ and -- are not atomic operations - they consist of a read, an increment/decrement and a store. For example if avail is 1 and avail++ and avail-- are executed on two different threads simultaneously then the end result could be 0, 1 or 2.